UNPKG

tone

Version:

A Web Audio framework for making interactive music in the browser.

308 lines (282 loc) 8.65 kB
define(["Tone/core/Tone", "Tone/component/CrossFade", "Tone/component/Merge", "Tone/component/Split", "Tone/signal/Signal", "Tone/signal/AudioToGain", "Tone/signal/Zero"], function(Tone){ "use strict"; /** * @class Both Tone.Panner3D and Tone.Listener have a position in 3D space * using a right-handed cartesian coordinate system. * The units used in the coordinate system are not defined; * these coordinates are independent/invariant of any particular * units such as meters or feet. Tone.Panner3D objects have an forward * vector representing the direction the sound is projecting. Additionally, * they have a sound cone representing how directional the sound is. * For example, the sound could be omnidirectional, in which case it would * be heard anywhere regardless of its forward, or it can be more directional * and heard only if it is facing the listener. Tone.Listener objects * (representing a person's ears) have an forward and up vector * representing in which direction the person is facing. Because both the * source stream and the listener can be moving, they both have a velocity * vector representing both the speed and direction of movement. Taken together, * these two velocities can be used to generate a doppler shift effect which changes the pitch. * <br><br> * Note: the position of the Listener will have no effect on nodes not connected to a Tone.Panner3D * * @constructor * @extends {Tone} * @singleton */ Tone.Listener = function(){ Tone.call(this); /** * Holds the current forward orientation * @type {Array} * @private */ this._orientation = [0, 0, 0, 0, 0, 0]; /** * Holds the current position * @type {Array} * @private */ this._position = [0, 0, 0]; Tone.getContext(function(){ // set the default position/forward this.set(ListenerConstructor.defaults); }.bind(this)); }; Tone.extend(Tone.Listener); /** * Defaults according to the specification * @static * @const * @type {Object} */ Tone.Listener.defaults = { "positionX" : 0, "positionY" : 0, "positionZ" : 0, "forwardX" : 0, "forwardY" : 0, "forwardZ" : 1, "upX" : 0, "upY" : 1, "upZ" : 0 }; /** * The ramp time which is applied to the setTargetAtTime * @type {Number} * @private */ Tone.Listener.prototype._rampTimeConstant = 0.01; /** * Sets the position of the listener in 3d space. * @param {Number} x * @param {Number} y * @param {Number} z * @return {Tone.Listener} this */ Tone.Listener.prototype.setPosition = function(x, y, z){ if (this.context.listener.positionX){ var now = this.now(); this.context.listener.positionX.setTargetAtTime(x, now, this._rampTimeConstant); this.context.listener.positionY.setTargetAtTime(y, now, this._rampTimeConstant); this.context.listener.positionZ.setTargetAtTime(z, now, this._rampTimeConstant); } else { this.context.listener.setPosition(x, y, z); } this._position = Array.prototype.slice.call(arguments); return this; }; /** * Sets the orientation of the listener using two vectors, the forward * vector (which direction the listener is facing) and the up vector * (which the up direction of the listener). An up vector * of 0, 0, 1 is equivalent to the listener standing up in the Z direction. * @param {Number} x * @param {Number} y * @param {Number} z * @param {Number} upX * @param {Number} upY * @param {Number} upZ * @return {Tone.Listener} this */ Tone.Listener.prototype.setOrientation = function(x, y, z, upX, upY, upZ){ if (this.context.listener.forwardX){ var now = this.now(); this.context.listener.forwardX.setTargetAtTime(x, now, this._rampTimeConstant); this.context.listener.forwardY.setTargetAtTime(y, now, this._rampTimeConstant); this.context.listener.forwardZ.setTargetAtTime(z, now, this._rampTimeConstant); this.context.listener.upX.setTargetAtTime(upX, now, this._rampTimeConstant); this.context.listener.upY.setTargetAtTime(upY, now, this._rampTimeConstant); this.context.listener.upZ.setTargetAtTime(upZ, now, this._rampTimeConstant); } else { this.context.listener.setOrientation(x, y, z, upX, upY, upZ); } this._orientation = Array.prototype.slice.call(arguments); return this; }; /** * The x position of the panner object. * @type {Number} * @memberOf Tone.Listener# * @name positionX */ Object.defineProperty(Tone.Listener.prototype, "positionX", { set : function(pos){ this._position[0] = pos; this.setPosition.apply(this, this._position); }, get : function(){ return this._position[0]; } }); /** * The y position of the panner object. * @type {Number} * @memberOf Tone.Listener# * @name positionY */ Object.defineProperty(Tone.Listener.prototype, "positionY", { set : function(pos){ this._position[1] = pos; this.setPosition.apply(this, this._position); }, get : function(){ return this._position[1]; } }); /** * The z position of the panner object. * @type {Number} * @memberOf Tone.Listener# * @name positionZ */ Object.defineProperty(Tone.Listener.prototype, "positionZ", { set : function(pos){ this._position[2] = pos; this.setPosition.apply(this, this._position); }, get : function(){ return this._position[2]; } }); /** * The x coordinate of the listeners front direction. i.e. * which way they are facing. * @type {Number} * @memberOf Tone.Listener# * @name forwardX */ Object.defineProperty(Tone.Listener.prototype, "forwardX", { set : function(pos){ this._orientation[0] = pos; this.setOrientation.apply(this, this._orientation); }, get : function(){ return this._orientation[0]; } }); /** * The y coordinate of the listeners front direction. i.e. * which way they are facing. * @type {Number} * @memberOf Tone.Listener# * @name forwardY */ Object.defineProperty(Tone.Listener.prototype, "forwardY", { set : function(pos){ this._orientation[1] = pos; this.setOrientation.apply(this, this._orientation); }, get : function(){ return this._orientation[1]; } }); /** * The z coordinate of the listeners front direction. i.e. * which way they are facing. * @type {Number} * @memberOf Tone.Listener# * @name forwardZ */ Object.defineProperty(Tone.Listener.prototype, "forwardZ", { set : function(pos){ this._orientation[2] = pos; this.setOrientation.apply(this, this._orientation); }, get : function(){ return this._orientation[2]; } }); /** * The x coordinate of the listener's up direction. i.e. * the direction the listener is standing in. * @type {Number} * @memberOf Tone.Listener# * @name upX */ Object.defineProperty(Tone.Listener.prototype, "upX", { set : function(pos){ this._orientation[3] = pos; this.setOrientation.apply(this, this._orientation); }, get : function(){ return this._orientation[3]; } }); /** * The y coordinate of the listener's up direction. i.e. * the direction the listener is standing in. * @type {Number} * @memberOf Tone.Listener# * @name upY */ Object.defineProperty(Tone.Listener.prototype, "upY", { set : function(pos){ this._orientation[4] = pos; this.setOrientation.apply(this, this._orientation); }, get : function(){ return this._orientation[4]; } }); /** * The z coordinate of the listener's up direction. i.e. * the direction the listener is standing in. * @type {Number} * @memberOf Tone.Listener# * @name upZ */ Object.defineProperty(Tone.Listener.prototype, "upZ", { set : function(pos){ this._orientation[5] = pos; this.setOrientation.apply(this, this._orientation); }, get : function(){ return this._orientation[5]; } }); /** * Clean up. * @returns {Tone.Listener} this */ Tone.Listener.prototype.dispose = function(){ this._orientation = null; this._position = null; return this; }; //SINGLETON SETUP var ListenerConstructor = Tone.Listener; Tone.Listener = new ListenerConstructor(); Tone.Context.on("init", function(context){ if (context.Listener instanceof ListenerConstructor){ //a single listener object Tone.Listener = context.Listener; } else { //make new Listener insides Tone.Listener = new ListenerConstructor(); } context.Listener = Tone.Listener; }); //END SINGLETON SETUP return Tone.Listener; });