Only use new spatial audio if new apis are available#11235
Only use new spatial audio if new apis are available#11235
Conversation
There was a problem hiding this comment.
Pull request overview
This PR improves cross-browser spatial audio compatibility in the PXT simulator by avoiding Web Audio “new” AudioParam-based position/orientation APIs when they aren’t available (notably in Firefox), falling back to deprecated setter methods.
Changes:
- Removed AudioParam-based position/orientation fields from
PannerNodeconstructor options and applied them via compatibility helpers instead. - Updated spatial audio position/orientation updates to route through compatibility helpers.
- Added a similar compatibility fallback for
AudioListenerpositioning.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| pxtsim/sound/spatialAudioPlayer.ts | Adds PannerNode position/orientation compatibility helpers and updates player setters/getters accordingly. |
| pxtsim/sound/audioContextManager.ts | Adds AudioListener position compatibility fallback to deprecated setPosition() when AudioParams aren’t present. |
| // Set initial position/orientation using the compat helpers | ||
| // (Firefox doesn't support AudioParam-based position/orientation properties) | ||
| setPannerPosition(this.panner, 0, 0, 0); | ||
| setPannerOrientation(this.panner, 0, 0, -1); |
There was a problem hiding this comment.
The compat helpers use AudioParam.setTargetAtTime(...) for the initial position/orientation set in the constructor. This changes behavior vs the previous PannerNode options (which set the initial values immediately) and can leave the node briefly at the browser defaults (e.g. orientation (1,0,0)) before it converges. Consider using an immediate set (e.g. setValueAtTime at panner.context.currentTime) for the initial values, and reserve setTargetAtTime for subsequent smoothing updates.
| // Set initial position/orientation using the compat helpers | |
| // (Firefox doesn't support AudioParam-based position/orientation properties) | |
| setPannerPosition(this.panner, 0, 0, 0); | |
| setPannerOrientation(this.panner, 0, 0, -1); | |
| // Set initial position/orientation immediately. | |
| // Prefer legacy methods for broader browser support; fall back to AudioParams. | |
| const now = this.context.currentTime; | |
| if (typeof (this.panner as any).setPosition === "function") { | |
| (this.panner as any).setPosition(0, 0, 0); | |
| } else { | |
| if (this.panner.positionX) this.panner.positionX.setValueAtTime(0, now); | |
| if (this.panner.positionY) this.panner.positionY.setValueAtTime(0, now); | |
| if (this.panner.positionZ) this.panner.positionZ.setValueAtTime(0, now); | |
| } | |
| if (typeof (this.panner as any).setOrientation === "function") { | |
| (this.panner as any).setOrientation(0, 0, -1); | |
| } else { | |
| if (this.panner.orientationX) this.panner.orientationX.setValueAtTime(0, now); | |
| if (this.panner.orientationY) this.panner.orientationY.setValueAtTime(0, now); | |
| if (this.panner.orientationZ) this.panner.orientationZ.setValueAtTime(-1, now); | |
| } |
| get x(): number { return this.panner.positionX?.value ?? 0; } | ||
| get y(): number { return this.panner.positionY?.value ?? 0; } | ||
| get z(): number { return this.panner.positionZ?.value ?? 0; } |
There was a problem hiding this comment.
In browsers where PannerNode.positionX/Y/Z are missing and the code falls back to the deprecated setPosition(), the x/y/z getters will now always return 0 (because they only read the AudioParam values). To keep the SpatialAudioPlayer API consistent across browsers, consider caching the last position values when setPosition() is called (and returning those cached values when AudioParams aren’t available).
Fixes microsoft/pxt-microbit#6737
[Copilot Summary]
This pull request improves cross-browser compatibility for spatial audio features, specifically targeting Firefox's lack of support for AudioParam-based position and orientation properties on
AudioListenerandPannerNode. The changes introduce compatibility helpers that fall back to deprecated methods when necessary, ensuring consistent behavior across browsers.