@babylonjs/viewer
Version:
The Babylon Viewer aims to simplify a specific but common Babylon.js use case: loading, viewing, and interacting with a 3D model.
150 lines (147 loc) • 5.61 kB
JavaScript
import { A as AbstractSoundSource } from './abstractSoundSource-5MTb28Na.esm.js';
import { _ as _HasSpatialAudioOptions, a as _StereoAudio, b as _SpatialWebAudio, c as _WebAudioBusAndSoundSubGraph } from './spatialWebAudio-BHkDY-w9.esm.js';
import './webAudioBaseSubGraph-BjGMAHX6.esm.js';
import './spatialWebAudioUpdaterComponent-jS7MKp73.esm.js';
import './index-MZPybX0H.esm.js';
/** @internal */
class _WebAudioSoundSource extends AbstractSoundSource {
/** @internal */
constructor(name, webAudioNode, engine, options) {
super(name, engine, options);
this._stereo = null;
this._webAudioNode = null;
this._mediaStreamAudioElement = null;
this._stopMediaStreamTracksOnDispose = false;
this._audioContext = this.engine._audioContext;
this._webAudioNode = webAudioNode;
this._stopMediaStreamTracksOnDispose = options.stopMediaStreamTracksOnDispose === true;
if (options.mediaStreamSinkEnabled !== false && webAudioNode instanceof MediaStreamAudioSourceNode) {
this._attachMediaStreamSink(webAudioNode.mediaStream);
}
this._subGraph = new _WebAudioSoundSource._SubGraph(this);
}
/**
* Keeps a `MediaStream`-backed source audible by attaching the stream to a hidden, muted audio element.
*
* Some browsers (notably Chromium) only deliver samples from a `MediaStreamAudioSourceNode` while its `MediaStream`
* is also being pulled by an `HTMLMediaElement`; without this, a remote WebRTC stream routed through Web Audio is
* silent and cannot be spatialized. The element is muted so it does not add a second, non-spatial playback.
* @param mediaStream - the `MediaStream` backing this sound source
*/
_attachMediaStreamSink(mediaStream) {
if (typeof Audio === "undefined") {
return;
}
const mediaElement = new Audio();
mediaElement.muted = true;
mediaElement.srcObject = mediaStream;
this._mediaStreamAudioElement = mediaElement;
void this._startMediaStreamSinkAsync(mediaElement);
}
/**
* Starts best-effort playback of the muted keep-alive media element.
* @param mediaElement - the muted media element pulling the source `MediaStream`
*/
async _startMediaStreamSinkAsync(mediaElement) {
try {
// Muted media is allowed to autoplay without a user gesture.
await mediaElement.play();
}
catch {
// A rejected play() only means this browser-specific keep-alive is unavailable, which is non-fatal.
}
}
/** @internal */
async _initAsync(options) {
if (options.outBus) {
this.outBus = options.outBus;
}
else if (options.outBusAutoDefault !== false) {
await this.engine.isReadyPromise;
this.outBus = this.engine.defaultMainBus;
}
await this._subGraph.initAsync(options);
if (_HasSpatialAudioOptions(options)) {
this._initSpatialProperty();
}
this.engine._addNode(this);
}
/** @internal */
get _inNode() {
return this._webAudioNode;
}
/** @internal */
get _outNode() {
return this._subGraph._outNode;
}
/** @internal */
get stereo() {
return this._stereo ?? (this._stereo = new _StereoAudio(this._subGraph));
}
/** @internal */
dispose() {
super.dispose();
if (this._mediaStreamAudioElement) {
this._mediaStreamAudioElement.pause();
this._mediaStreamAudioElement.srcObject = null;
this._mediaStreamAudioElement = null;
}
if (this._webAudioNode) {
if (this._stopMediaStreamTracksOnDispose && this._webAudioNode instanceof MediaStreamAudioSourceNode) {
for (const track of this._webAudioNode.mediaStream.getTracks()) {
track.stop();
}
}
this._webAudioNode.disconnect();
this._webAudioNode = null;
}
this._stereo = null;
this._subGraph.dispose();
this.engine._removeNode(this);
}
/** @internal */
getClassName() {
return "_WebAudioSoundSource";
}
_connect(node) {
const connected = super._connect(node);
if (!connected) {
return false;
}
// If the wrapped node is not available now, it will be connected later by the subgraph.
if (node._inNode) {
this._outNode?.connect(node._inNode);
}
return true;
}
_disconnect(node) {
const disconnected = super._disconnect(node);
if (!disconnected) {
return false;
}
if (node._inNode) {
this._outNode?.disconnect(node._inNode);
}
return true;
}
_createSpatialProperty(autoUpdate, minUpdateTime) {
return new _SpatialWebAudio(this._subGraph, autoUpdate, minUpdateTime);
}
}
_WebAudioSoundSource._SubGraph = class extends _WebAudioBusAndSoundSubGraph {
get _downstreamNodes() {
return this._owner._downstreamNodes ?? null;
}
get _upstreamNodes() {
return this._owner._upstreamNodes ?? null;
}
_onSubNodesChanged() {
super._onSubNodesChanged();
this._owner._inNode?.disconnect();
if (this._owner._subGraph._inNode) {
this._owner._inNode?.connect(this._owner._subGraph._inNode);
}
}
};
export { _WebAudioSoundSource };
//# sourceMappingURL=webAudioSoundSource-BpDGX_V9.esm.js.map