initial commit
This commit is contained in:
319
lib/audio/Audio.js
Normal file
319
lib/audio/Audio.js
Normal file
@ -0,0 +1,319 @@
|
||||
/**
|
||||
* @author mrdoob / http://mrdoob.com/
|
||||
* @author Reece Aaron Lecrivain / http://reecenotes.com/
|
||||
*/
|
||||
|
||||
import { Object3D } from '../core/Object3D.js';
|
||||
|
||||
function Audio( listener ) {
|
||||
|
||||
Object3D.call( this );
|
||||
|
||||
this.type = 'Audio';
|
||||
|
||||
this.context = listener.context;
|
||||
|
||||
this.gain = this.context.createGain();
|
||||
this.gain.connect( listener.getInput() );
|
||||
|
||||
this.autoplay = false;
|
||||
|
||||
this.buffer = null;
|
||||
this.loop = false;
|
||||
this.startTime = 0;
|
||||
this.offset = 0;
|
||||
this.playbackRate = 1;
|
||||
this.isPlaying = false;
|
||||
this.hasPlaybackControl = true;
|
||||
this.sourceType = 'empty';
|
||||
|
||||
this.filters = [];
|
||||
|
||||
}
|
||||
|
||||
Audio.prototype = Object.assign( Object.create( Object3D.prototype ), {
|
||||
|
||||
constructor: Audio,
|
||||
|
||||
getOutput: function () {
|
||||
|
||||
return this.gain;
|
||||
|
||||
},
|
||||
|
||||
setNodeSource: function ( audioNode ) {
|
||||
|
||||
this.hasPlaybackControl = false;
|
||||
this.sourceType = 'audioNode';
|
||||
this.source = audioNode;
|
||||
this.connect();
|
||||
|
||||
return this;
|
||||
|
||||
},
|
||||
|
||||
setMediaElementSource: function ( mediaElement ) {
|
||||
|
||||
this.hasPlaybackControl = false;
|
||||
this.sourceType = 'mediaNode';
|
||||
this.source = this.context.createMediaElementSource( mediaElement );
|
||||
this.connect();
|
||||
|
||||
return this;
|
||||
|
||||
},
|
||||
|
||||
setBuffer: function ( audioBuffer ) {
|
||||
|
||||
this.buffer = audioBuffer;
|
||||
this.sourceType = 'buffer';
|
||||
|
||||
if ( this.autoplay ) this.play();
|
||||
|
||||
return this;
|
||||
|
||||
},
|
||||
|
||||
play: function () {
|
||||
|
||||
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;
|
||||
|
||||
}
|
||||
|
||||
var source = this.context.createBufferSource();
|
||||
|
||||
source.buffer = this.buffer;
|
||||
source.loop = this.loop;
|
||||
source.onended = this.onEnded.bind( this );
|
||||
source.playbackRate.setValueAtTime( this.playbackRate, this.startTime );
|
||||
this.startTime = this.context.currentTime;
|
||||
source.start( this.startTime, this.offset );
|
||||
|
||||
this.isPlaying = true;
|
||||
|
||||
this.source = source;
|
||||
|
||||
return this.connect();
|
||||
|
||||
},
|
||||
|
||||
pause: function () {
|
||||
|
||||
if ( this.hasPlaybackControl === false ) {
|
||||
|
||||
console.warn( 'THREE.Audio: this Audio has no playback control.' );
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
if ( this.isPlaying === true ) {
|
||||
|
||||
this.source.stop();
|
||||
this.source.onended = null;
|
||||
this.offset += ( this.context.currentTime - this.startTime ) * this.playbackRate;
|
||||
this.isPlaying = false;
|
||||
|
||||
}
|
||||
|
||||
return this;
|
||||
|
||||
},
|
||||
|
||||
stop: function () {
|
||||
|
||||
if ( this.hasPlaybackControl === false ) {
|
||||
|
||||
console.warn( 'THREE.Audio: this Audio has no playback control.' );
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
this.source.stop();
|
||||
this.source.onended = null;
|
||||
this.offset = 0;
|
||||
this.isPlaying = false;
|
||||
|
||||
return this;
|
||||
|
||||
},
|
||||
|
||||
connect: function () {
|
||||
|
||||
if ( this.filters.length > 0 ) {
|
||||
|
||||
this.source.connect( this.filters[ 0 ] );
|
||||
|
||||
for ( var 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() );
|
||||
|
||||
}
|
||||
|
||||
return this;
|
||||
|
||||
},
|
||||
|
||||
disconnect: function () {
|
||||
|
||||
if ( this.filters.length > 0 ) {
|
||||
|
||||
this.source.disconnect( this.filters[ 0 ] );
|
||||
|
||||
for ( var 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() );
|
||||
|
||||
}
|
||||
|
||||
return this;
|
||||
|
||||
},
|
||||
|
||||
getFilters: function () {
|
||||
|
||||
return this.filters;
|
||||
|
||||
},
|
||||
|
||||
setFilters: function ( value ) {
|
||||
|
||||
if ( ! value ) value = [];
|
||||
|
||||
if ( this.isPlaying === true ) {
|
||||
|
||||
this.disconnect();
|
||||
this.filters = value;
|
||||
this.connect();
|
||||
|
||||
} else {
|
||||
|
||||
this.filters = value;
|
||||
|
||||
}
|
||||
|
||||
return this;
|
||||
|
||||
},
|
||||
|
||||
getFilter: function () {
|
||||
|
||||
return this.getFilters()[ 0 ];
|
||||
|
||||
},
|
||||
|
||||
setFilter: function ( filter ) {
|
||||
|
||||
return this.setFilters( filter ? [ filter ] : [] );
|
||||
|
||||
},
|
||||
|
||||
setPlaybackRate: function ( 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.setValueAtTime( this.playbackRate, this.context.currentTime );
|
||||
|
||||
}
|
||||
|
||||
return this;
|
||||
|
||||
},
|
||||
|
||||
getPlaybackRate: function () {
|
||||
|
||||
return this.playbackRate;
|
||||
|
||||
},
|
||||
|
||||
onEnded: function () {
|
||||
|
||||
this.isPlaying = false;
|
||||
|
||||
},
|
||||
|
||||
getLoop: function () {
|
||||
|
||||
if ( this.hasPlaybackControl === false ) {
|
||||
|
||||
console.warn( 'THREE.Audio: this Audio has no playback control.' );
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
return this.loop;
|
||||
|
||||
},
|
||||
|
||||
setLoop: function ( 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;
|
||||
|
||||
},
|
||||
|
||||
getVolume: function () {
|
||||
|
||||
return this.gain.gain.value;
|
||||
|
||||
},
|
||||
|
||||
setVolume: function ( value ) {
|
||||
|
||||
this.gain.gain.setTargetAtTime( value, this.context.currentTime, 0.01 );
|
||||
|
||||
return this;
|
||||
|
||||
}
|
||||
|
||||
} );
|
||||
|
||||
export { Audio };
|
42
lib/audio/AudioAnalyser.js
Normal file
42
lib/audio/AudioAnalyser.js
Normal file
@ -0,0 +1,42 @@
|
||||
/**
|
||||
* @author mrdoob / http://mrdoob.com/
|
||||
*/
|
||||
|
||||
function AudioAnalyser( audio, fftSize ) {
|
||||
|
||||
this.analyser = audio.context.createAnalyser();
|
||||
this.analyser.fftSize = fftSize !== undefined ? fftSize : 2048;
|
||||
|
||||
this.data = new Uint8Array( this.analyser.frequencyBinCount );
|
||||
|
||||
audio.getOutput().connect( this.analyser );
|
||||
|
||||
}
|
||||
|
||||
Object.assign( AudioAnalyser.prototype, {
|
||||
|
||||
getFrequencyData: function () {
|
||||
|
||||
this.analyser.getByteFrequencyData( this.data );
|
||||
|
||||
return this.data;
|
||||
|
||||
},
|
||||
|
||||
getAverageFrequency: function () {
|
||||
|
||||
var value = 0, data = this.getFrequencyData();
|
||||
|
||||
for ( var i = 0; i < data.length; i ++ ) {
|
||||
|
||||
value += data[ i ];
|
||||
|
||||
}
|
||||
|
||||
return value / data.length;
|
||||
|
||||
}
|
||||
|
||||
} );
|
||||
|
||||
export { AudioAnalyser };
|
29
lib/audio/AudioContext.js
Normal file
29
lib/audio/AudioContext.js
Normal file
@ -0,0 +1,29 @@
|
||||
/**
|
||||
* @author mrdoob / http://mrdoob.com/
|
||||
*/
|
||||
|
||||
var context;
|
||||
|
||||
var AudioContext = {
|
||||
|
||||
getContext: function () {
|
||||
|
||||
if ( context === undefined ) {
|
||||
|
||||
context = new ( window.AudioContext || window.webkitAudioContext )();
|
||||
|
||||
}
|
||||
|
||||
return context;
|
||||
|
||||
},
|
||||
|
||||
setContext: function ( value ) {
|
||||
|
||||
context = value;
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
export { AudioContext };
|
135
lib/audio/AudioListener.js
Normal file
135
lib/audio/AudioListener.js
Normal file
@ -0,0 +1,135 @@
|
||||
/**
|
||||
* @author mrdoob / http://mrdoob.com/
|
||||
*/
|
||||
|
||||
import { Vector3 } from '../math/Vector3.js';
|
||||
import { Quaternion } from '../math/Quaternion.js';
|
||||
import { Object3D } from '../core/Object3D.js';
|
||||
import { AudioContext } from './AudioContext.js';
|
||||
|
||||
function AudioListener() {
|
||||
|
||||
Object3D.call( this );
|
||||
|
||||
this.type = 'AudioListener';
|
||||
|
||||
this.context = AudioContext.getContext();
|
||||
|
||||
this.gain = this.context.createGain();
|
||||
this.gain.connect( this.context.destination );
|
||||
|
||||
this.filter = null;
|
||||
|
||||
}
|
||||
|
||||
AudioListener.prototype = Object.assign( Object.create( Object3D.prototype ), {
|
||||
|
||||
constructor: AudioListener,
|
||||
|
||||
getInput: function () {
|
||||
|
||||
return this.gain;
|
||||
|
||||
},
|
||||
|
||||
removeFilter: function ( ) {
|
||||
|
||||
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;
|
||||
|
||||
},
|
||||
|
||||
getFilter: function () {
|
||||
|
||||
return this.filter;
|
||||
|
||||
},
|
||||
|
||||
setFilter: function ( 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;
|
||||
|
||||
},
|
||||
|
||||
getMasterVolume: function () {
|
||||
|
||||
return this.gain.gain.value;
|
||||
|
||||
},
|
||||
|
||||
setMasterVolume: function ( value ) {
|
||||
|
||||
this.gain.gain.setTargetAtTime( value, this.context.currentTime, 0.01 );
|
||||
|
||||
return this;
|
||||
|
||||
},
|
||||
|
||||
updateMatrixWorld: ( function () {
|
||||
|
||||
var position = new Vector3();
|
||||
var quaternion = new Quaternion();
|
||||
var scale = new Vector3();
|
||||
|
||||
var orientation = new Vector3();
|
||||
|
||||
return function updateMatrixWorld( force ) {
|
||||
|
||||
Object3D.prototype.updateMatrixWorld.call( this, force );
|
||||
|
||||
var listener = this.context.listener;
|
||||
var up = this.up;
|
||||
|
||||
this.matrixWorld.decompose( position, quaternion, scale );
|
||||
|
||||
orientation.set( 0, 0, - 1 ).applyQuaternion( quaternion );
|
||||
|
||||
if ( listener.positionX ) {
|
||||
|
||||
listener.positionX.setValueAtTime( position.x, this.context.currentTime );
|
||||
listener.positionY.setValueAtTime( position.y, this.context.currentTime );
|
||||
listener.positionZ.setValueAtTime( position.z, this.context.currentTime );
|
||||
listener.forwardX.setValueAtTime( orientation.x, this.context.currentTime );
|
||||
listener.forwardY.setValueAtTime( orientation.y, this.context.currentTime );
|
||||
listener.forwardZ.setValueAtTime( orientation.z, this.context.currentTime );
|
||||
listener.upX.setValueAtTime( up.x, this.context.currentTime );
|
||||
listener.upY.setValueAtTime( up.y, this.context.currentTime );
|
||||
listener.upZ.setValueAtTime( up.z, this.context.currentTime );
|
||||
|
||||
} else {
|
||||
|
||||
listener.setPosition( position.x, position.y, position.z );
|
||||
listener.setOrientation( orientation.x, orientation.y, orientation.z, up.x, up.y, up.z );
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
} )()
|
||||
|
||||
} );
|
||||
|
||||
export { AudioListener };
|
122
lib/audio/PositionalAudio.js
Normal file
122
lib/audio/PositionalAudio.js
Normal file
@ -0,0 +1,122 @@
|
||||
/**
|
||||
* @author mrdoob / http://mrdoob.com/
|
||||
*/
|
||||
|
||||
import { Vector3 } from '../math/Vector3.js';
|
||||
import { Quaternion } from '../math/Quaternion.js';
|
||||
import { Audio } from './Audio.js';
|
||||
import { Object3D } from '../core/Object3D.js';
|
||||
|
||||
function PositionalAudio( listener ) {
|
||||
|
||||
Audio.call( this, listener );
|
||||
|
||||
this.panner = this.context.createPanner();
|
||||
this.panner.connect( this.gain );
|
||||
|
||||
}
|
||||
|
||||
PositionalAudio.prototype = Object.assign( Object.create( Audio.prototype ), {
|
||||
|
||||
constructor: PositionalAudio,
|
||||
|
||||
getOutput: function () {
|
||||
|
||||
return this.panner;
|
||||
|
||||
},
|
||||
|
||||
getRefDistance: function () {
|
||||
|
||||
return this.panner.refDistance;
|
||||
|
||||
},
|
||||
|
||||
setRefDistance: function ( value ) {
|
||||
|
||||
this.panner.refDistance = value;
|
||||
|
||||
return this;
|
||||
|
||||
},
|
||||
|
||||
getRolloffFactor: function () {
|
||||
|
||||
return this.panner.rolloffFactor;
|
||||
|
||||
},
|
||||
|
||||
setRolloffFactor: function ( value ) {
|
||||
|
||||
this.panner.rolloffFactor = value;
|
||||
|
||||
return this;
|
||||
|
||||
},
|
||||
|
||||
getDistanceModel: function () {
|
||||
|
||||
return this.panner.distanceModel;
|
||||
|
||||
},
|
||||
|
||||
setDistanceModel: function ( value ) {
|
||||
|
||||
this.panner.distanceModel = value;
|
||||
|
||||
return this;
|
||||
|
||||
},
|
||||
|
||||
getMaxDistance: function () {
|
||||
|
||||
return this.panner.maxDistance;
|
||||
|
||||
},
|
||||
|
||||
setMaxDistance: function ( value ) {
|
||||
|
||||
this.panner.maxDistance = value;
|
||||
|
||||
return this;
|
||||
|
||||
},
|
||||
|
||||
setDirectionalCone: function ( coneInnerAngle, coneOuterAngle, coneOuterGain ) {
|
||||
|
||||
this.panner.coneInnerAngle = coneInnerAngle;
|
||||
this.panner.coneOuterAngle = coneOuterAngle;
|
||||
this.panner.coneOuterGain = coneOuterGain;
|
||||
|
||||
return this;
|
||||
|
||||
},
|
||||
|
||||
updateMatrixWorld: ( function () {
|
||||
|
||||
var position = new Vector3();
|
||||
var quaternion = new Quaternion();
|
||||
var scale = new Vector3();
|
||||
|
||||
var orientation = new Vector3();
|
||||
|
||||
return function updateMatrixWorld( force ) {
|
||||
|
||||
Object3D.prototype.updateMatrixWorld.call( this, force );
|
||||
|
||||
var panner = this.panner;
|
||||
this.matrixWorld.decompose( position, quaternion, scale );
|
||||
|
||||
orientation.set( 0, 0, 1 ).applyQuaternion( quaternion );
|
||||
|
||||
panner.setPosition( position.x, position.y, position.z );
|
||||
panner.setOrientation( orientation.x, orientation.y, orientation.z );
|
||||
|
||||
};
|
||||
|
||||
} )()
|
||||
|
||||
|
||||
} );
|
||||
|
||||
export { PositionalAudio };
|
Reference in New Issue
Block a user