123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170 |
- /**
- * @author alteredq / http://alteredqualia.com/
- *
- * AudioObject
- *
- * - 3d spatialized sound with Doppler-shift effect
- *
- * - uses Audio API (currently supported in WebKit-based browsers)
- * https://dvcs.w3.org/hg/audio/raw-file/tip/webaudio/specification.html
- *
- * - based on Doppler effect demo from Chromium
- * http://chromium.googlecode.com/svn/trunk/samples/audio/doppler.html
- *
- * - parameters
- *
- * - listener
- * dopplerFactor // A constant used to determine the amount of pitch shift to use when rendering a doppler effect.
- * speedOfSound // The speed of sound used for calculating doppler shift. The default value is 343.3 meters / second.
- *
- * - panner
- * refDistance // A reference distance for reducing volume as source move further from the listener.
- * maxDistance // The maximum distance between source and listener, after which the volume will not be reduced any further.
- * rolloffFactor // Describes how quickly the volume is reduced as source moves away from listener.
- * coneInnerAngle // An angle inside of which there will be no volume reduction.
- * coneOuterAngle // An angle outside of which the volume will be reduced to a constant value of coneOuterGain.
- * coneOuterGain // Amount of volume reduction outside of the coneOuterAngle.
- */
- THREE.AudioObject = function ( url, volume, playbackRate, loop ) {
- THREE.Object3D.call( this );
- if ( playbackRate === undefined ) playbackRate = 1;
- if ( volume === undefined ) volume = 1;
- if ( loop === undefined ) loop = true;
- if ( ! this.context ) {
- try {
- THREE.AudioObject.prototype.context = new webkitAudioContext();
- } catch( error ) {
- console.warn( "THREE.AudioObject: webkitAudioContext not found" );
- return this;
- }
- }
- this.directionalSource = false;
- this.listener = this.context.listener;
- this.panner = this.context.createPanner();
- this.source = this.context.createBufferSource();
- this.masterGainNode = this.context.createGainNode();
- this.dryGainNode = this.context.createGainNode();
- // Setup initial gains
- this.masterGainNode.gain.value = volume;
- this.dryGainNode.gain.value = 3.0;
- // Connect dry mix
- this.source.connect( this.panner );
- this.panner.connect( this.dryGainNode );
- this.dryGainNode.connect( this.masterGainNode );
- // Connect master gain
- this.masterGainNode.connect( this.context.destination );
- // Set source parameters and load sound
- this.source.playbackRate.value = playbackRate;
- this.source.loop = loop;
- loadBufferAndPlay( url );
- // private properties
- var soundPosition = new THREE.Vector3(),
- cameraPosition = new THREE.Vector3(),
- oldSoundPosition = new THREE.Vector3(),
- oldCameraPosition = new THREE.Vector3(),
- soundDelta = new THREE.Vector3(),
- cameraDelta = new THREE.Vector3(),
- soundFront = new THREE.Vector3(),
- cameraFront = new THREE.Vector3(),
- soundUp = new THREE.Vector3(),
- cameraUp = new THREE.Vector3();
- var _this = this;
- // API
- this.setVolume = function ( volume ) {
- this.masterGainNode.gain.value = volume;
- };
- this.update = function ( camera ) {
- oldSoundPosition.copy( soundPosition );
- oldCameraPosition.copy( cameraPosition );
- soundPosition.setFromMatrixPosition( this.matrixWorld );
- cameraPosition.setFromMatrixPosition( camera.matrixWorld );
- soundDelta.subVectors( soundPosition, oldSoundPosition );
- cameraDelta.subVectors( cameraPosition, oldCameraPosition );
- cameraUp.copy( camera.up );
- cameraFront.set( 0, 0, -1 );
- cameraFront.transformDirection( camera.matrixWorld );
- this.listener.setPosition( cameraPosition.x, cameraPosition.y, cameraPosition.z );
- this.listener.setVelocity( cameraDelta.x, cameraDelta.y, cameraDelta.z );
- this.listener.setOrientation( cameraFront.x, cameraFront.y, cameraFront.z, cameraUp.x, cameraUp.y, cameraUp.z );
- this.panner.setPosition( soundPosition.x, soundPosition.y, soundPosition.z );
- this.panner.setVelocity( soundDelta.x, soundDelta.y, soundDelta.z );
- if ( this.directionalSource ) {
- soundFront.set( 0, 0, -1 );
- soundFront.transformDirection( this.matrixWorld );
- soundUp.copy( this.up );
- this.panner.setOrientation( soundFront.x, soundFront.y, soundFront.z, soundUp.x, soundUp.y, soundUp.z );
- }
- };
- function loadBufferAndPlay( url ) {
- // Load asynchronously
- var request = new XMLHttpRequest();
- request.open( "GET", url, true );
- request.responseType = "arraybuffer";
- request.onload = function() {
- _this.source.buffer = _this.context.createBuffer( request.response, true );
- _this.source.noteOn( 0 );
- }
- request.send();
- }
- };
- THREE.AudioObject.prototype = Object.create( THREE.Object3D.prototype );
- THREE.AudioObject.prototype.constructor = THREE.AudioObject;
- THREE.AudioObject.prototype.context = null;
- THREE.AudioObject.prototype.type = null;
|