main repo

This commit is contained in:
Basilosaurusrex
2025-11-24 18:09:40 +01:00
parent b636ee5e70
commit f027651f9b
34146 changed files with 4436636 additions and 0 deletions

777
node_modules/three/src/audio/Audio.js generated vendored Normal file
View File

@@ -0,0 +1,777 @@
import { Object3D } from '../core/Object3D.js';
/**
* Represents a non-positional ( global ) audio object.
*
* This and related audio modules make use of the [Web Audio API]{@link https://www.w3.org/TR/webaudio-1.1/}.
*
* ```js
* // create an AudioListener and add it to the camera
* const listener = new THREE.AudioListener();
* camera.add( listener );
*
* // create a global audio source
* const sound = new THREE.Audio( listener );
*
* // load a sound and set it as the Audio object's buffer
* const audioLoader = new THREE.AudioLoader();
* audioLoader.load( 'sounds/ambient.ogg', function( buffer ) {
* sound.setBuffer( buffer );
* sound.setLoop( true );
* sound.setVolume( 0.5 );
* sound.play();
* });
* ```
*
* @augments Object3D
*/
class Audio extends Object3D {
/**
* Constructs a new audio.
*
* @param {AudioListener} listener - The global audio listener.
*/
constructor( listener ) {
super();
this.type = 'Audio';
/**
* The global audio listener.
*
* @type {AudioListener}
* @readonly
*/
this.listener = listener;
/**
* The audio context.
*
* @type {AudioContext}
* @readonly
*/
this.context = listener.context;
/**
* The gain node used for volume control.
*
* @type {GainNode}
* @readonly
*/
this.gain = this.context.createGain();
this.gain.connect( listener.getInput() );
/**
* Whether to start playback automatically or not.
*
* @type {boolean}
* @default false
*/
this.autoplay = false;
/**
* A reference to an audio buffer.
*
* Defined via {@link Audio#setBuffer}.
*
* @type {?AudioBuffer}
* @default null
* @readonly
*/
this.buffer = null;
/**
* Modify pitch, measured in cents. +/- 100 is a semitone.
* +/- 1200 is an octave.
*
* Defined via {@link Audio#setDetune}.
*
* @type {number}
* @default 0
* @readonly
*/
this.detune = 0;
/**
* Whether the audio should loop or not.
*
* Defined via {@link Audio#setLoop}.
*
* @type {boolean}
* @default false
* @readonly
*/
this.loop = false;
/**
* Defines where in the audio buffer the replay should
* start, in seconds.
*
* @type {number}
* @default 0
*/
this.loopStart = 0;
/**
* Defines where in the audio buffer the replay should
* stop, in seconds.
*
* @type {number}
* @default 0
*/
this.loopEnd = 0;
/**
* An offset to the time within the audio buffer the playback
* should begin, in seconds.
*
* @type {number}
* @default 0
*/
this.offset = 0;
/**
* Overrides the default duration of the audio.
*
* @type {undefined|number}
* @default undefined
*/
this.duration = undefined;
/**
* The playback speed.
*
* Defined via {@link Audio#setPlaybackRate}.
*
* @type {number}
* @readonly
* @default 1
*/
this.playbackRate = 1;
/**
* Indicates whether the audio is playing or not.
*
* This flag will be automatically set when using {@link Audio#play},
* {@link Audio#pause}, {@link Audio#stop}.
*
* @type {boolean}
* @readonly
* @default false
*/
this.isPlaying = false;
/**
* Indicates whether the audio playback can be controlled
* with method like {@link Audio#play} or {@link Audio#pause}.
*
* This flag will be automatically set when audio sources are
* defined.
*
* @type {boolean}
* @readonly
* @default true
*/
this.hasPlaybackControl = true;
/**
* Holds a reference to the current audio source.
*
* The property is automatically by one of the `set*()` methods.
*
* @type {?AudioNode}
* @readonly
* @default null
*/
this.source = null;
/**
* Defines the source type.
*
* The property is automatically by one of the `set*()` methods.
*
* @type {('empty'|'audioNode'|'mediaNode'|'mediaStreamNode'|'buffer')}
* @readonly
* @default 'empty'
*/
this.sourceType = 'empty';
this._startedAt = 0;
this._progress = 0;
this._connected = false;
/**
* Can be used to apply a variety of low-order filters to create
* more complex sound effects e.g. via `BiquadFilterNode`.
*
* The property is automatically set by {@link Audio#setFilters}.
*
* @type {Array<AudioNode>}
* @readonly
*/
this.filters = [];
}
/**
* Returns the output audio node.
*
* @return {GainNode} The output node.
*/
getOutput() {
return this.gain;
}
/**
* Sets the given audio node as the source of this instance.
*
* {@link Audio#sourceType} is set to `audioNode` and {@link Audio#hasPlaybackControl} to `false`.
*
* @param {AudioNode} audioNode - The audio node like an instance of `OscillatorNode`.
* @return {Audio} A reference to this instance.
*/
setNodeSource( audioNode ) {
this.hasPlaybackControl = false;
this.sourceType = 'audioNode';
this.source = audioNode;
this.connect();
return this;
}
/**
* Sets the given media element as the source of this instance.
*
* {@link Audio#sourceType} is set to `mediaNode` and {@link Audio#hasPlaybackControl} to `false`.
*
* @param {HTMLMediaElement} mediaElement - The media element.
* @return {Audio} A reference to this instance.
*/
setMediaElementSource( mediaElement ) {
this.hasPlaybackControl = false;
this.sourceType = 'mediaNode';
this.source = this.context.createMediaElementSource( mediaElement );
this.connect();
return this;
}
/**
* Sets the given media stream as the source of this instance.
*
* {@link Audio#sourceType} is set to `mediaStreamNode` and {@link Audio#hasPlaybackControl} to `false`.
*
* @param {MediaStream} mediaStream - The media stream.
* @return {Audio} A reference to this instance.
*/
setMediaStreamSource( mediaStream ) {
this.hasPlaybackControl = false;
this.sourceType = 'mediaStreamNode';
this.source = this.context.createMediaStreamSource( mediaStream );
this.connect();
return this;
}
/**
* Sets the given audio buffer as the source of this instance.
*
* {@link Audio#sourceType} is set to `buffer` and {@link Audio#hasPlaybackControl} to `true`.
*
* @param {AudioBuffer} audioBuffer - The audio buffer.
* @return {Audio} A reference to this instance.
*/
setBuffer( audioBuffer ) {
this.buffer = audioBuffer;
this.sourceType = 'buffer';
if ( this.autoplay ) this.play();
return this;
}
/**
* Starts the playback of the audio.
*
* Can only be used with compatible audio sources that allow playback control.
*
* @param {number} [delay=0] - The delay, in seconds, at which the audio should start playing.
* @return {Audio|undefined} A reference to this instance.
*/
play( delay = 0 ) {
if ( this.isPlaying === true ) {
console.warn( 'THREE.Audio: Audio is already playing.' );
return;
}
if ( this.hasPlaybackControl === false ) {
console.warn( 'THREE.Audio: this Audio has no playback control.' );
return;
}
this._startedAt = this.context.currentTime + delay;
const source = this.context.createBufferSource();
source.buffer = this.buffer;
source.loop = this.loop;
source.loopStart = this.loopStart;
source.loopEnd = this.loopEnd;
source.onended = this.onEnded.bind( this );
source.start( this._startedAt, this._progress + this.offset, this.duration );
this.isPlaying = true;
this.source = source;
this.setDetune( this.detune );
this.setPlaybackRate( this.playbackRate );
return this.connect();
}
/**
* Pauses the playback of the audio.
*
* Can only be used with compatible audio sources that allow playback control.
*
* @return {Audio|undefined} A reference to this instance.
*/
pause() {
if ( this.hasPlaybackControl === false ) {
console.warn( 'THREE.Audio: this Audio has no playback control.' );
return;
}
if ( this.isPlaying === true ) {
// update current progress
this._progress += Math.max( this.context.currentTime - this._startedAt, 0 ) * this.playbackRate;
if ( this.loop === true ) {
// ensure _progress does not exceed duration with looped audios
this._progress = this._progress % ( this.duration || this.buffer.duration );
}
this.source.stop();
this.source.onended = null;
this.isPlaying = false;
}
return this;
}
/**
* Stops the playback of the audio.
*
* Can only be used with compatible audio sources that allow playback control.
*
* @param {number} [delay=0] - The delay, in seconds, at which the audio should stop playing.
* @return {Audio|undefined} A reference to this instance.
*/
stop( delay = 0 ) {
if ( this.hasPlaybackControl === false ) {
console.warn( 'THREE.Audio: this Audio has no playback control.' );
return;
}
this._progress = 0;
if ( this.source !== null ) {
this.source.stop( this.context.currentTime + delay );
this.source.onended = null;
}
this.isPlaying = false;
return this;
}
/**
* Connects to the audio source. This is used internally on
* initialisation and when setting / removing filters.
*
* @return {Audio} A reference to this instance.
*/
connect() {
if ( this.filters.length > 0 ) {
this.source.connect( this.filters[ 0 ] );
for ( let i = 1, l = this.filters.length; i < l; i ++ ) {
this.filters[ i - 1 ].connect( this.filters[ i ] );
}
this.filters[ this.filters.length - 1 ].connect( this.getOutput() );
} else {
this.source.connect( this.getOutput() );
}
this._connected = true;
return this;
}
/**
* Disconnects to the audio source. This is used internally on
* initialisation and when setting / removing filters.
*
* @return {Audio|undefined} A reference to this instance.
*/
disconnect() {
if ( this._connected === false ) {
return;
}
if ( this.filters.length > 0 ) {
this.source.disconnect( this.filters[ 0 ] );
for ( let i = 1, l = this.filters.length; i < l; i ++ ) {
this.filters[ i - 1 ].disconnect( this.filters[ i ] );
}
this.filters[ this.filters.length - 1 ].disconnect( this.getOutput() );
} else {
this.source.disconnect( this.getOutput() );
}
this._connected = false;
return this;
}
/**
* Returns the current set filters.
*
* @return {Array<AudioNode>} The list of filters.
*/
getFilters() {
return this.filters;
}
/**
* Sets an array of filters and connects them with the audio source.
*
* @param {Array<AudioNode>} [value] - A list of filters.
* @return {Audio} A reference to this instance.
*/
setFilters( value ) {
if ( ! value ) value = [];
if ( this._connected === true ) {
this.disconnect();
this.filters = value.slice();
this.connect();
} else {
this.filters = value.slice();
}
return this;
}
/**
* Defines the detuning of oscillation in cents.
*
* @param {number} value - The detuning of oscillation in cents.
* @return {Audio} A reference to this instance.
*/
setDetune( value ) {
this.detune = value;
if ( this.isPlaying === true && this.source.detune !== undefined ) {
this.source.detune.setTargetAtTime( this.detune, this.context.currentTime, 0.01 );
}
return this;
}
/**
* Returns the detuning of oscillation in cents.
*
* @return {number} The detuning of oscillation in cents.
*/
getDetune() {
return this.detune;
}
/**
* Returns the first filter in the list of filters.
*
* @return {AudioNode|undefined} The first filter in the list of filters.
*/
getFilter() {
return this.getFilters()[ 0 ];
}
/**
* Applies a single filter node to the audio.
*
* @param {AudioNode} [filter] - The filter to set.
* @return {Audio} A reference to this instance.
*/
setFilter( filter ) {
return this.setFilters( filter ? [ filter ] : [] );
}
/**
* Sets the playback rate.
*
* Can only be used with compatible audio sources that allow playback control.
*
* @param {number} [value] - The playback rate to set.
* @return {Audio|undefined} A reference to this instance.
*/
setPlaybackRate( value ) {
if ( this.hasPlaybackControl === false ) {
console.warn( 'THREE.Audio: this Audio has no playback control.' );
return;
}
this.playbackRate = value;
if ( this.isPlaying === true ) {
this.source.playbackRate.setTargetAtTime( this.playbackRate, this.context.currentTime, 0.01 );
}
return this;
}
/**
* Returns the current playback rate.
* @return {number} The playback rate.
*/
getPlaybackRate() {
return this.playbackRate;
}
/**
* Automatically called when playback finished.
*/
onEnded() {
this.isPlaying = false;
this._progress = 0;
}
/**
* Returns the loop flag.
*
* Can only be used with compatible audio sources that allow playback control.
*
* @return {boolean} Whether the audio should loop or not.
*/
getLoop() {
if ( this.hasPlaybackControl === false ) {
console.warn( 'THREE.Audio: this Audio has no playback control.' );
return false;
}
return this.loop;
}
/**
* Sets the loop flag.
*
* Can only be used with compatible audio sources that allow playback control.
*
* @param {boolean} value - Whether the audio should loop or not.
* @return {Audio|undefined} A reference to this instance.
*/
setLoop( value ) {
if ( this.hasPlaybackControl === false ) {
console.warn( 'THREE.Audio: this Audio has no playback control.' );
return;
}
this.loop = value;
if ( this.isPlaying === true ) {
this.source.loop = this.loop;
}
return this;
}
/**
* Sets the loop start value which defines where in the audio buffer the replay should
* start, in seconds.
*
* @param {number} value - The loop start value.
* @return {Audio} A reference to this instance.
*/
setLoopStart( value ) {
this.loopStart = value;
return this;
}
/**
* Sets the loop end value which defines where in the audio buffer the replay should
* stop, in seconds.
*
* @param {number} value - The loop end value.
* @return {Audio} A reference to this instance.
*/
setLoopEnd( value ) {
this.loopEnd = value;
return this;
}
/**
* Returns the volume.
*
* @return {number} The volume.
*/
getVolume() {
return this.gain.gain.value;
}
/**
* Sets the volume.
*
* @param {number} value - The volume to set.
* @return {Audio} A reference to this instance.
*/
setVolume( value ) {
this.gain.gain.setTargetAtTime( value, this.context.currentTime, 0.01 );
return this;
}
copy( source, recursive ) {
super.copy( source, recursive );
if ( source.sourceType !== 'buffer' ) {
console.warn( 'THREE.Audio: Audio source type cannot be copied.' );
return this;
}
this.autoplay = source.autoplay;
this.buffer = source.buffer;
this.detune = source.detune;
this.loop = source.loop;
this.loopStart = source.loopStart;
this.loopEnd = source.loopEnd;
this.offset = source.offset;
this.duration = source.duration;
this.playbackRate = source.playbackRate;
this.hasPlaybackControl = source.hasPlaybackControl;
this.sourceType = source.sourceType;
this.filters = source.filters.slice();
return this;
}
clone( recursive ) {
return new this.constructor( this.listener ).copy( this, recursive );
}
}
export { Audio };

97
node_modules/three/src/audio/AudioAnalyser.js generated vendored Normal file
View File

@@ -0,0 +1,97 @@
/**
* This class can be used to analyse audio data.
*
* ```js
* // create an AudioListener and add it to the camera
* const listener = new THREE.AudioListener();
* camera.add( listener );
*
* // create an Audio source
* const sound = new THREE.Audio( listener );
*
* // load a sound and set it as the Audio object's buffer
* const audioLoader = new THREE.AudioLoader();
* audioLoader.load( 'sounds/ambient.ogg', function( buffer ) {
* sound.setBuffer( buffer );
* sound.setLoop(true);
* sound.setVolume(0.5);
* sound.play();
* });
*
* // create an AudioAnalyser, passing in the sound and desired fftSize
* const analyser = new THREE.AudioAnalyser( sound, 32 );
*
* // get the average frequency of the sound
* const data = analyser.getAverageFrequency();
* ```
*/
class AudioAnalyser {
/**
* Constructs a new audio analyzer.
*
* @param {Audio} audio - The audio to analyze.
* @param {number} [fftSize=2048] - The window size in samples that is used when performing a Fast Fourier Transform (FFT) to get frequency domain data.
*/
constructor( audio, fftSize = 2048 ) {
/**
* The global audio listener.
*
* @type {AnalyserNode}
*/
this.analyser = audio.context.createAnalyser();
this.analyser.fftSize = fftSize;
/**
* Holds the analyzed data.
*
* @type {Uint8Array}
*/
this.data = new Uint8Array( this.analyser.frequencyBinCount );
audio.getOutput().connect( this.analyser );
}
/**
* Returns an array with frequency data of the audio.
*
* Each item in the array represents the decibel value for a specific frequency.
* The frequencies are spread linearly from 0 to 1/2 of the sample rate.
* For example, for 48000 sample rate, the last item of the array will represent
* the decibel value for 24000 Hz.
*
* @return {Uint8Array} The frequency data.
*/
getFrequencyData() {
this.analyser.getByteFrequencyData( this.data );
return this.data;
}
/**
* Returns the average of the frequencies returned by {@link AudioAnalyser#getFrequencyData}.
*
* @return {number} The average frequency.
*/
getAverageFrequency() {
let value = 0;
const data = this.getFrequencyData();
for ( let i = 0; i < data.length; i ++ ) {
value += data[ i ];
}
return value / data.length;
}
}
export { AudioAnalyser };

40
node_modules/three/src/audio/AudioContext.js generated vendored Normal file
View File

@@ -0,0 +1,40 @@
let _context;
/**
* Manages the global audio context in the engine.
*
* @hideconstructor
*/
class AudioContext {
/**
* Returns the global native audio context.
*
* @return {AudioContext} The native audio context.
*/
static getContext() {
if ( _context === undefined ) {
_context = new ( window.AudioContext || window.webkitAudioContext )();
}
return _context;
}
/**
* Allows to set the global native audio context from outside.
*
* @param {AudioContext} value - The native context to set.
*/
static setContext( value ) {
_context = value;
}
}
export { AudioContext };

216
node_modules/three/src/audio/AudioListener.js generated vendored Normal file
View File

@@ -0,0 +1,216 @@
import { Vector3 } from '../math/Vector3.js';
import { Quaternion } from '../math/Quaternion.js';
import { Clock } from '../core/Clock.js';
import { Object3D } from '../core/Object3D.js';
import { AudioContext } from './AudioContext.js';
const _position = /*@__PURE__*/ new Vector3();
const _quaternion = /*@__PURE__*/ new Quaternion();
const _scale = /*@__PURE__*/ new Vector3();
const _forward = /*@__PURE__*/ new Vector3();
const _up = /*@__PURE__*/ new Vector3();
/**
* The class represents a virtual listener of the all positional and non-positional audio effects
* in the scene. A three.js application usually creates a single listener. It is a mandatory
* constructor parameter for audios entities like {@link Audio} and {@link PositionalAudio}.
*
* In most cases, the listener object is a child of the camera. So the 3D transformation of the
* camera represents the 3D transformation of the listener.
*
* @augments Object3D
*/
class AudioListener extends Object3D {
/**
* Constructs a new audio listener.
*/
constructor() {
super();
this.type = 'AudioListener';
/**
* The native audio context.
*
* @type {AudioContext}
* @readonly
*/
this.context = AudioContext.getContext();
/**
* The gain node used for volume control.
*
* @type {GainNode}
* @readonly
*/
this.gain = this.context.createGain();
this.gain.connect( this.context.destination );
/**
* An optional filter.
*
* Defined via {@link AudioListener#setFilter}.
*
* @type {?AudioNode}
* @default null
* @readonly
*/
this.filter = null;
/**
* Time delta values required for `linearRampToValueAtTime()` usage.
*
* @type {number}
* @default 0
* @readonly
*/
this.timeDelta = 0;
// private
this._clock = new Clock();
}
/**
* Returns the listener's input node.
*
* This method is used by other audio nodes to connect to this listener.
*
* @return {GainNode} The input node.
*/
getInput() {
return this.gain;
}
/**
* Removes the current filter from this listener.
*
* @return {AudioListener} A reference to this listener.
*/
removeFilter() {
if ( this.filter !== null ) {
this.gain.disconnect( this.filter );
this.filter.disconnect( this.context.destination );
this.gain.connect( this.context.destination );
this.filter = null;
}
return this;
}
/**
* Returns the current set filter.
*
* @return {?AudioNode} The filter.
*/
getFilter() {
return this.filter;
}
/**
* Sets the given filter to this listener.
*
* @param {AudioNode} value - The filter to set.
* @return {AudioListener} A reference to this listener.
*/
setFilter( value ) {
if ( this.filter !== null ) {
this.gain.disconnect( this.filter );
this.filter.disconnect( this.context.destination );
} else {
this.gain.disconnect( this.context.destination );
}
this.filter = value;
this.gain.connect( this.filter );
this.filter.connect( this.context.destination );
return this;
}
/**
* Returns the applications master volume.
*
* @return {number} The master volume.
*/
getMasterVolume() {
return this.gain.gain.value;
}
/**
* Sets the applications master volume. This volume setting affects
* all audio nodes in the scene.
*
* @param {number} value - The master volume to set.
* @return {AudioListener} A reference to this listener.
*/
setMasterVolume( value ) {
this.gain.gain.setTargetAtTime( value, this.context.currentTime, 0.01 );
return this;
}
updateMatrixWorld( force ) {
super.updateMatrixWorld( force );
const listener = this.context.listener;
this.timeDelta = this._clock.getDelta();
this.matrixWorld.decompose( _position, _quaternion, _scale );
// the initial forward and up directions must be orthogonal
_forward.set( 0, 0, - 1 ).applyQuaternion( _quaternion );
_up.set( 0, 1, 0 ).applyQuaternion( _quaternion );
if ( listener.positionX ) {
// code path for Chrome (see #14393)
const endTime = this.context.currentTime + this.timeDelta;
listener.positionX.linearRampToValueAtTime( _position.x, endTime );
listener.positionY.linearRampToValueAtTime( _position.y, endTime );
listener.positionZ.linearRampToValueAtTime( _position.z, endTime );
listener.forwardX.linearRampToValueAtTime( _forward.x, endTime );
listener.forwardY.linearRampToValueAtTime( _forward.y, endTime );
listener.forwardZ.linearRampToValueAtTime( _forward.z, endTime );
listener.upX.linearRampToValueAtTime( _up.x, endTime );
listener.upY.linearRampToValueAtTime( _up.y, endTime );
listener.upZ.linearRampToValueAtTime( _up.z, endTime );
} else {
listener.setPosition( _position.x, _position.y, _position.z );
listener.setOrientation( _forward.x, _forward.y, _forward.z, _up.x, _up.y, _up.z );
}
}
}
export { AudioListener };

253
node_modules/three/src/audio/PositionalAudio.js generated vendored Normal file
View File

@@ -0,0 +1,253 @@
import { Vector3 } from '../math/Vector3.js';
import { Quaternion } from '../math/Quaternion.js';
import { Audio } from './Audio.js';
const _position = /*@__PURE__*/ new Vector3();
const _quaternion = /*@__PURE__*/ new Quaternion();
const _scale = /*@__PURE__*/ new Vector3();
const _orientation = /*@__PURE__*/ new Vector3();
/**
* Represents a positional audio object.
*
* ```js
* // create an AudioListener and add it to the camera
* const listener = new THREE.AudioListener();
* camera.add( listener );
*
* // create the PositionalAudio object (passing in the listener)
* const sound = new THREE.PositionalAudio( listener );
*
* // load a sound and set it as the PositionalAudio object's buffer
* const audioLoader = new THREE.AudioLoader();
* audioLoader.load( 'sounds/song.ogg', function( buffer ) {
* sound.setBuffer( buffer );
* sound.setRefDistance( 20 );
* sound.play();
* });
*
* // create an object for the sound to play from
* const sphere = new THREE.SphereGeometry( 20, 32, 16 );
* const material = new THREE.MeshPhongMaterial( { color: 0xff2200 } );
* const mesh = new THREE.Mesh( sphere, material );
* scene.add( mesh );
*
* // finally add the sound to the mesh
* mesh.add( sound );
*
* @augments Audio
*/
class PositionalAudio extends Audio {
/**
* Constructs a positional audio.
*
* @param {AudioListener} listener - The global audio listener.
*/
constructor( listener ) {
super( listener );
/**
* The panner node represents the location, direction, and behavior of an audio
* source in 3D space.
*
* @type {PannerNode}
* @readonly
*/
this.panner = this.context.createPanner();
this.panner.panningModel = 'HRTF';
this.panner.connect( this.gain );
}
connect() {
super.connect();
this.panner.connect( this.gain );
return this;
}
disconnect() {
super.disconnect();
this.panner.disconnect( this.gain );
return this;
}
getOutput() {
return this.panner;
}
/**
* Returns the current reference distance.
*
* @return {number} The reference distance.
*/
getRefDistance() {
return this.panner.refDistance;
}
/**
* Defines the reference distance for reducing volume as the audio source moves
* further from the listener i.e. the distance at which the volume reduction
* starts taking effect.
*
* @param {number} value - The reference distance to set.
* @return {PositionalAudio} A reference to this instance.
*/
setRefDistance( value ) {
this.panner.refDistance = value;
return this;
}
/**
* Returns the current rolloff factor.
*
* @return {number} The rolloff factor.
*/
getRolloffFactor() {
return this.panner.rolloffFactor;
}
/**
* Defines how quickly the volume is reduced as the source moves away from the listener.
*
* @param {number} value - The rolloff factor.
* @return {PositionalAudio} A reference to this instance.
*/
setRolloffFactor( value ) {
this.panner.rolloffFactor = value;
return this;
}
/**
* Returns the current distance model.
*
* @return {('linear'|'inverse'|'exponential')} The distance model.
*/
getDistanceModel() {
return this.panner.distanceModel;
}
/**
* Defines which algorithm to use to reduce the volume of the audio source
* as it moves away from the listener.
*
* Read [the spec]{@link https://www.w3.org/TR/webaudio-1.1/#enumdef-distancemodeltype}
* for more details.
*
* @param {('linear'|'inverse'|'exponential')} value - The distance model to set.
* @return {PositionalAudio} A reference to this instance.
*/
setDistanceModel( value ) {
this.panner.distanceModel = value;
return this;
}
/**
* Returns the current max distance.
*
* @return {number} The max distance.
*/
getMaxDistance() {
return this.panner.maxDistance;
}
/**
* Defines the maximum distance between the audio source and the listener,
* after which the volume is not reduced any further.
*
* This value is used only by the `linear` distance model.
*
* @param {number} value - The max distance.
* @return {PositionalAudio} A reference to this instance.
*/
setMaxDistance( value ) {
this.panner.maxDistance = value;
return this;
}
/**
* Sets the directional cone in which the audio can be listened.
*
* @param {number} coneInnerAngle - An angle, in degrees, of a cone inside of which there will be no volume reduction.
* @param {number} coneOuterAngle - An angle, in degrees, of a cone outside of which the volume will be reduced by a constant value, defined by the `coneOuterGain` parameter.
* @param {number} coneOuterGain - The amount of volume reduction outside the cone defined by the `coneOuterAngle`. When set to `0`, no sound can be heard.
* @return {PositionalAudio} A reference to this instance.
*/
setDirectionalCone( coneInnerAngle, coneOuterAngle, coneOuterGain ) {
this.panner.coneInnerAngle = coneInnerAngle;
this.panner.coneOuterAngle = coneOuterAngle;
this.panner.coneOuterGain = coneOuterGain;
return this;
}
updateMatrixWorld( force ) {
super.updateMatrixWorld( force );
if ( this.hasPlaybackControl === true && this.isPlaying === false ) return;
this.matrixWorld.decompose( _position, _quaternion, _scale );
_orientation.set( 0, 0, 1 ).applyQuaternion( _quaternion );
const panner = this.panner;
if ( panner.positionX ) {
// code path for Chrome and Firefox (see #14393)
const endTime = this.context.currentTime + this.listener.timeDelta;
panner.positionX.linearRampToValueAtTime( _position.x, endTime );
panner.positionY.linearRampToValueAtTime( _position.y, endTime );
panner.positionZ.linearRampToValueAtTime( _position.z, endTime );
panner.orientationX.linearRampToValueAtTime( _orientation.x, endTime );
panner.orientationY.linearRampToValueAtTime( _orientation.y, endTime );
panner.orientationZ.linearRampToValueAtTime( _orientation.z, endTime );
} else {
panner.setPosition( _position.x, _position.y, _position.z );
panner.setOrientation( _orientation.x, _orientation.y, _orientation.z );
}
}
}
export { PositionalAudio };