Spaces:
Running
Running
/** | |
* @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.listener = listener; | |
this.context = listener.context; | |
this.gain = this.context.createGain(); | |
this.gain.connect( listener.getInput() ); | |
this.autoplay = false; | |
this.buffer = null; | |
this.detune = 0; | |
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 ); | |
this.startTime = this.context.currentTime; | |
source.start( this.startTime, this.offset ); | |
this.isPlaying = true; | |
this.source = source; | |
this.setDetune( this.detune ); | |
this.setPlaybackRate( this.playbackRate ); | |
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; | |
}, | |
setDetune: function ( value ) { | |
this.detune = value; | |
if ( this.source.detune === undefined ) return; // only set detune when available | |
if ( this.isPlaying === true ) { | |
this.source.detune.setTargetAtTime( this.detune, this.context.currentTime, 0.01 ); | |
} | |
return this; | |
}, | |
getDetune: function () { | |
return this.detune; | |
}, | |
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.setTargetAtTime( this.playbackRate, this.context.currentTime, 0.01 ); | |
} | |
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 }; | |