Buckets:
| 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 }; | |
Xet Storage Details
- Size:
- 15.3 kB
- Xet hash:
- 5f4435c29627a39ce22c6f1b1531f3889469560e8dfc768bbe510fd65cb573e8
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.