Start · Sprachen · JavaScript · Referenz · AudioScheduledSourceNode

AudioScheduledSourceNode

Schnittstelle

Abstrakte Basisschnittstelle der Web Audio API für Quellknoten, die sich zeitgenau mit <code>start()</code> und <code>stop()</code> planen lassen und dann das Ereignis <code>ended</code> auslösen.

seit JavaScript Baseline: alle modernen Browser (seit 2021 als eig Kategorie: webapi

Signatur

interface AudioScheduledSourceNode extends AudioNode

Beschreibung

AudioScheduledSourceNode ist eine abstrakte Basisschnittstelle der Web Audio API. Sie erbt von AudioNode und bündelt die gemeinsame Planungslogik aller Quellknoten, die zu einem bestimmten Zeitpunkt der Audio-Zeitachse starten und stoppen. Dazu gehören AudioBufferSourceNode, OscillatorNode und ConstantSourceNode.

Die Schnittstelle stellt drei Bausteine bereit:

  • start(when?): startet die Wiedergabe zum Zeitpunkt when, gemessen in Sekunden auf der Uhr AudioContext.currentTime.
  • stop(when?): beendet die Wiedergabe zum angegebenen Zeitpunkt.
  • ended: Ereignis, das feuert, sobald die Wiedergabe endet. Das passiert durch stop() oder, bei Puffern, am Ende der Daten. Man kann es mit addEventListener("ended", …) oder über die Eigenschaft onended abonnieren.

Man erzeugt AudioScheduledSourceNode nie direkt. Stattdessen nutzt man eine der abgeleiteten Klassen, entweder mit einem Konstruktor wie new OscillatorNode(ctx) oder mit einer Fabrikmethode wie ctx.createOscillator(). Die zeitgenaue Planung ist wichtig für Sequenzer, Metronome, Spiele-Soundeffekte und Synthesizer. Die Zeitpunkte gelten auf der Audio-Uhr und sind deshalb sehr viel genauer als setTimeout.

Jeder Quellknoten ist ein Einweg-Objekt: start() darf pro Knoten nur einmal aufgerufen werden. Wer einen Ton erneut abspielen will, erzeugt einen neuen Knoten. Das ist günstig und so vorgesehen.

Parameter

Name Typ Default Beschreibung
$when number 0 Gilt für start(when) und stop(when): Zeitpunkt in Sekunden auf der Uhr AudioContext.currentTime. Liegt der Wert in der Vergangenheit oder ist er 0, wird sofort gestartet bzw. gestoppt. Negative Werte lösen einen RangeError aus.

Rückgabewert

Typ
void
Beschreibung
start() und stop() geben undefined zurück. Das Ende der Wiedergabe meldet das Ereignis ended. Bei AudioBufferSourceNode.start() sind zusätzlich die Parameter offset und duration möglich.

Beispiele

Oszillator erzeugen und für eine Sekunde abspielen

const ctx = new AudioContext();

// OscillatorNode erbt von AudioScheduledSourceNode
const osc = new OscillatorNode(ctx, { type: 'sine', frequency: 440 });
osc.connect(ctx.destination);

const now = ctx.currentTime;
osc.start(now);       // sofort starten
osc.stop(now + 1);    // nach genau 1 Sekunde stoppen

console.log(osc instanceof AudioScheduledSourceNode);
true

Ende der Wiedergabe mit addEventListener und onended erkennen

const ctx = new AudioContext();

const playBeep = (freq, duration) => new Promise((resolve) => {
  const osc = ctx.createOscillator();
  osc.frequency.value = freq;
  osc.connect(ctx.destination);

  osc.addEventListener('ended', () => {
    osc.disconnect(); // Ressourcen freigeben
    resolve(freq);
  }, { once: true });

  osc.start();
  osc.stop(ctx.currentTime + duration);
});

// Alternative: on-Property
const c = ctx.createConstantSource();
c.onended = () => console.log('ConstantSource beendet');
c.start();
c.stop(ctx.currentTime + 0.1);

document.querySelector('#play').addEventListener('click', async () => {
  await ctx.resume(); // Autoplay-Richtlinie
  const f = await playBeep(660, 0.3);
  console.log(`Ton ${f} Hz fertig`);
});
ConstantSource beendet Ton 660 Hz fertig

Metronom: Klicks exakt auf der Audio-Zeitachse planen

const ctx = new AudioContext();

const scheduleClick = (time, accent) => {
  const osc = new OscillatorNode(ctx, { frequency: accent ? 1500 : 1000 });
  const gain = new GainNode(ctx, { gain: 0.5 });
  osc.connect(gain).connect(ctx.destination);
  // Jeder Klick ist ein neuer Knoten, weil start() nur einmal erlaubt ist
  osc.start(time);
  osc.stop(time + 0.05);
};

const bpm = 120;
const beat = 60 / bpm;
const startAt = ctx.currentTime + 0.1;

for (let i = 0; i < 8; i++) {
  scheduleClick(startAt + i * beat, i % 4 === 0);
}
console.log(`8 Klicks geplant, Abstand ${beat} s`);
8 Klicks geplant, Abstand 0.5 s

// Wichtig · Fallstricke

  • Nur ein start() pro Knoten: Ein zweiter Aufruf wirft einen InvalidStateError. Ein stop() vor start() wirft ebenfalls einen InvalidStateError. Für eine erneute Wiedergabe erzeugt man einen neuen Knoten. Gestoppte Knoten ohne Verbindung und ohne Referenz räumt der Garbage Collector ab.
  • Mehrere stop()-Aufrufe: Ein späterer Aufruf ersetzt den zuvor geplanten Stoppzeitpunkt. So lässt sich eine Note verlängern oder vorzeitig beenden.
  • Autoplay-Richtlinien: Browser starten einen AudioContext oft im Zustand "suspended". Man ruft ctx.resume() in einem Handler für eine Nutzeraktion auf, zum Beispiel einem Klick. Sonst bleibt die Wiedergabe stumm, obwohl start() fehlerfrei durchläuft.
  • Zeitbasis: when bezieht sich auf AudioContext.currentTime, nicht auf performance.now() oder Date.now(). Man plant am besten etwas in die Zukunft, zum Beispiel mit currentTime + 0.05, damit es keine Knackser und keine verschluckten Starts gibt.
  • Knacksen vermeiden: Ein hartes stop() kann ein Klicken erzeugen. Deshalb blendet man die Lautstärke vorher über einen GainNode aus, etwa mit linearRampToValueAtTime.
  • Kompatibilität: Alle modernen Browser unterstützen das Interface. Ältere Safari-Versionen brauchten webkitAudioContext, und sehr alte Implementierungen kannten noteOn()/noteOff() statt start()/stop(). Den Konstruktor AudioScheduledSourceNode kann man nicht direkt aufrufen, er wirft einen TypeError.