Signatur
Beschreibung
AudioListener steht für die „Ohren“ einer 3D-Audioszene. Zu jedem BaseAudioContext gehört genau ein Listener, den du über context.listener erreichst. Einen Konstruktor gibt es nicht. Alle PannerNode-Knoten im selben Kontext berechnen Lautstärke, Stereo-Panning und (bei panningModel = "HRTF") die richtungsabhängige Klangfärbung aus dem Verhältnis zwischen Schallquelle und Listener.
Die Position setzt du über positionX, positionY und positionZ. Die Ausrichtung wird durch zwei Vektoren festgelegt: den Blickrichtungsvektor (forwardX/Y/Z, Standard 0, 0, -1) und den Oben-Vektor (upX/Y/Z, Standard 0, 1, 0). Alle neun Eigenschaften sind AudioParam-Objekte. Du kannst sie also direkt über .value setzen oder mit setValueAtTime(), linearRampToValueAtTime() und ähnlichen Methoden sample-genau automatisieren.
Typische Einsatzfälle sind Spiele, WebXR- und VR-Anwendungen, 3D-Visualisierungen und virtuelle Räume, in denen sich die Kamera oder der Spieler bewegt. Meist führst du den Listener in jedem Frame mit der Kamera nach. Das Koordinatensystem ist rechtshändig: +X zeigt nach rechts, +Y nach oben, und –Z ist die Standard-Blickrichtung.
Die älteren Methoden setPosition(x, y, z) und setOrientation(fx, fy, fz, ux, uy, uz) sind veraltet. Sie funktionieren zwar noch, du solltest aber die AudioParam-Eigenschaften bevorzugen.
Rückgabewert
BaseAudioContext.listener abgerufen. Pro Kontext gibt es genau eine Instanz.Beispiele
Listener abrufen und Position setzen (mit Fallback)
const ctx = new AudioContext();
const listener = ctx.listener;
// Listener an Position (0, 1.7, 5) setzen, etwa Augenhöhe eines Spielers
if (listener.positionX) {
listener.positionX.value = 0;
listener.positionY.value = 1.7;
listener.positionZ.value = 5;
} else {
// Fallback für ältere Browser
listener.setPosition(0, 1.7, 5);
}
console.log(listener.positionZ?.value);
Schallquelle im Raum mit PannerNode hören
const ctx = new AudioContext();
const { listener } = ctx;
// Zuhörer im Ursprung, Blick nach -Z
listener.forwardX.value = 0;
listener.forwardY.value = 0;
listener.forwardZ.value = -1;
listener.upY.value = 1;
// Oszillator 3 Einheiten rechts vom Zuhörer platzieren
const osc = new OscillatorNode(ctx, { frequency: 440 });
const panner = new PannerNode(ctx, {
panningModel: 'HRTF',
distanceModel: 'inverse',
positionX: 3,
positionY: 0,
positionZ: 0
});
osc.connect(panner).connect(ctx.destination);
document.querySelector('#play').addEventListener('click', async () => {
await ctx.resume(); // Autoplay-Sperre aufheben
osc.start();
osc.stop(ctx.currentTime + 2);
});
Listener pro Frame mit der Kamera mitdrehen
const ctx = new AudioContext();
const { listener } = ctx;
let yaw = 0; // Drehung um die Y-Achse in Radiant
const update = () => {
yaw += 0.01;
const t = ctx.currentTime;
// Blickrichtung aus dem Drehwinkel berechnen
listener.forwardX.setTargetAtTime(Math.sin(yaw), t, 0.02);
listener.forwardZ.setTargetAtTime(-Math.cos(yaw), t, 0.02);
requestAnimationFrame(update);
};
requestAnimationFrame(update);
Sanfte Bewegung durch Automatisierung
const ctx = new AudioContext();
const { listener } = ctx;
const now = ctx.currentTime;
// Listener in 4 Sekunden von z = 10 nach z = -10 bewegen
listener.positionZ.setValueAtTime(10, now);
listener.positionZ.linearRampToValueAtTime(-10, now + 4);
// Wichtig · Fallstricke
- Kein Konstruktor:
new AudioListener()löst einenTypeErroraus. Hole den Listener immer überctx.listener. - Kompatibilität: Chrome, Edge und Safari unterstützen die
AudioParam-Eigenschaften (positionXusw.) schon lange. Firefox unterstützt sie erst ab Version 125, ältere Versionen nursetPosition()undsetOrientation(). Prüfe daher per Feature-Erkennung (if (listener.positionX)). - Veraltete Methoden:
setPosition()undsetOrientation()heben laufende Automatisierungen auf den zugehörigenAudioParams nicht sauber auf. Mische beide Ansätze nicht. - Oben- und Blickrichtungsvektor dürfen nicht parallel sein, sonst ist die Ausrichtung nicht definiert. Die Folge können Klangsprünge sein.
- Wirkung nur mit PannerNode: Der Listener beeinflusst ausschließlich
PannerNode.StereoPannerNodeignoriert ihn. - Performance: Wenn du pro Frame direkt
.valuesetzt, kann es knacken.setTargetAtTime()glättet die Übergänge. Das HRTF-Modell ist rechenintensiver als"equalpower". - Seit der Autoplay-Richtlinie startet ein
AudioContextoft im Zustandsuspended. Ruferesume()nach einer Nutzerinteraktion auf.