mirror of
https://github.com/Tonejs/Tone.js
synced 2024-11-16 08:38:00 +00:00
276 lines
6.1 KiB
JavaScript
276 lines
6.1 KiB
JavaScript
import Tone from "../../core/Tone";
|
|
import "../source/Player";
|
|
import "../component/Volume";
|
|
import "../core/AudioNode";
|
|
|
|
/**
|
|
* @class Tone.Players combines multiple [Tone.Player](Player) objects.
|
|
*
|
|
* @constructor
|
|
* @extends {Tone.AudioNode}
|
|
* @param {Object} urls An object mapping a name to a url.
|
|
* @param {function=} onload The function to invoke when all buffers are loaded.
|
|
*/
|
|
Tone.Players = function(urls) {
|
|
|
|
var args = Array.prototype.slice.call(arguments);
|
|
args.shift();
|
|
var options = Tone.defaults(args, ["onload"], Tone.Players);
|
|
Tone.AudioNode.call(this, options);
|
|
|
|
/**
|
|
* The output volume node
|
|
* @type {Tone.Volume}
|
|
* @private
|
|
*/
|
|
this._volume = this.output = new Tone.Volume(options.volume);
|
|
|
|
/**
|
|
* The volume of the output in decibels.
|
|
* @type {Decibels}
|
|
* @signal
|
|
* @example
|
|
* source.volume.value = -6;
|
|
*/
|
|
this.volume = this._volume.volume;
|
|
this._readOnly("volume");
|
|
|
|
//make the output explicitly stereo
|
|
this._volume.output.output.channelCount = 2;
|
|
this._volume.output.output.channelCountMode = "explicit";
|
|
//mute initially
|
|
this.mute = options.mute;
|
|
|
|
/**
|
|
* The container of all of the players
|
|
* @type {Object}
|
|
* @private
|
|
*/
|
|
this._players = {};
|
|
|
|
/**
|
|
* The loading count
|
|
* @type {Number}
|
|
* @private
|
|
*/
|
|
this._loadingCount = 0;
|
|
|
|
/**
|
|
* private holder of the fadeIn time
|
|
* @type {Time}
|
|
* @private
|
|
*/
|
|
this._fadeIn = options.fadeIn;
|
|
|
|
/**
|
|
* private holder of the fadeOut time
|
|
* @type {Time}
|
|
* @private
|
|
*/
|
|
this._fadeOut = options.fadeOut;
|
|
|
|
//add all of the players
|
|
for (var name in urls) {
|
|
this._loadingCount++;
|
|
this.add(name, urls[name], this._bufferLoaded.bind(this, options.onload));
|
|
}
|
|
};
|
|
|
|
Tone.extend(Tone.Players, Tone.AudioNode);
|
|
|
|
/**
|
|
* The default values
|
|
* @type {Object}
|
|
*/
|
|
Tone.Players.defaults = {
|
|
"volume" : 0,
|
|
"mute" : false,
|
|
"onload" : Tone.noOp,
|
|
"fadeIn" : 0,
|
|
"fadeOut" : 0,
|
|
};
|
|
|
|
/**
|
|
* A buffer was loaded. decrement the counter.
|
|
* @param {Function} callback
|
|
* @private
|
|
*/
|
|
Tone.Players.prototype._bufferLoaded = function(callback) {
|
|
this._loadingCount--;
|
|
if (this._loadingCount === 0 && callback) {
|
|
callback(this);
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Mute the output.
|
|
* @memberOf Tone.Source#
|
|
* @type {boolean}
|
|
* @name mute
|
|
* @example
|
|
* //mute the output
|
|
* source.mute = true;
|
|
*/
|
|
Object.defineProperty(Tone.Players.prototype, "mute", {
|
|
get : function() {
|
|
return this._volume.mute;
|
|
},
|
|
set : function(mute) {
|
|
this._volume.mute = mute;
|
|
},
|
|
});
|
|
|
|
/**
|
|
* The fadeIn time of the amplitude envelope.
|
|
* @memberOf Tone.Source#
|
|
* @type {Time}
|
|
* @name fadeIn
|
|
*/
|
|
Object.defineProperty(Tone.Players.prototype, "fadeIn", {
|
|
get : function() {
|
|
return this._fadeIn;
|
|
},
|
|
set : function(fadeIn) {
|
|
this._fadeIn = fadeIn;
|
|
this._forEach(function(player) {
|
|
player.fadeIn = fadeIn;
|
|
});
|
|
},
|
|
});
|
|
|
|
/**
|
|
* The fadeOut time of the amplitude envelope.
|
|
* @memberOf Tone.Source#
|
|
* @type {Time}
|
|
* @name fadeOut
|
|
*/
|
|
Object.defineProperty(Tone.Players.prototype, "fadeOut", {
|
|
get : function() {
|
|
return this._fadeOut;
|
|
},
|
|
set : function(fadeOut) {
|
|
this._fadeOut = fadeOut;
|
|
this._forEach(function(player) {
|
|
player.fadeOut = fadeOut;
|
|
});
|
|
},
|
|
});
|
|
|
|
/**
|
|
* The state of the players object. Returns "started" if any of the players are playing.
|
|
* @memberOf Tone.Players#
|
|
* @type {String}
|
|
* @name state
|
|
* @readOnly
|
|
*/
|
|
Object.defineProperty(Tone.Players.prototype, "state", {
|
|
get : function() {
|
|
var playing = false;
|
|
this._forEach(function(player) {
|
|
playing = playing || player.state === Tone.State.Started;
|
|
});
|
|
return playing ? Tone.State.Started : Tone.State.Stopped;
|
|
},
|
|
});
|
|
|
|
/**
|
|
* True if the buffers object has a buffer by that name.
|
|
* @param {String|Number} name The key or index of the
|
|
* buffer.
|
|
* @return {Boolean}
|
|
*/
|
|
Tone.Players.prototype.has = function(name) {
|
|
return this._players.hasOwnProperty(name);
|
|
};
|
|
|
|
/**
|
|
* Get a player by name.
|
|
* @param {String} name The players name as defined in
|
|
* the constructor object or `add` method.
|
|
* @return {Tone.Player}
|
|
*/
|
|
Tone.Players.prototype.get = function(name) {
|
|
if (this.has(name)) {
|
|
return this._players[name];
|
|
} else {
|
|
throw new Error("Tone.Players: no player named " + name);
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Iterate over all of the players
|
|
* @param {Function} callback
|
|
* @return {Tone.Players} this
|
|
* @private
|
|
*/
|
|
Tone.Players.prototype._forEach = function(callback) {
|
|
for (var playerName in this._players) {
|
|
callback(this._players[playerName], playerName);
|
|
}
|
|
return this;
|
|
};
|
|
|
|
/**
|
|
* If all the buffers are loaded or not
|
|
* @memberOf Tone.Players#
|
|
* @type {Boolean}
|
|
* @name loaded
|
|
* @readOnly
|
|
*/
|
|
Object.defineProperty(Tone.Players.prototype, "loaded", {
|
|
get : function() {
|
|
var isLoaded = true;
|
|
this._forEach(function(player) {
|
|
isLoaded = isLoaded && player.loaded;
|
|
});
|
|
return isLoaded;
|
|
},
|
|
});
|
|
|
|
/**
|
|
* Add a player by name and url to the Players
|
|
* @param {String} name A unique name to give the player
|
|
* @param {String|Tone.Buffer|Audiobuffer} url Either the url of the bufer,
|
|
* or a buffer which will be added
|
|
* with the given name.
|
|
* @param {Function=} callback The callback to invoke
|
|
* when the url is loaded.
|
|
*/
|
|
Tone.Players.prototype.add = function(name, url, callback) {
|
|
this._players[name] = new Tone.Player(url, callback).connect(this.output);
|
|
this._players[name].fadeIn = this._fadeIn;
|
|
this._players[name].fadeOut = this._fadeOut;
|
|
return this;
|
|
};
|
|
|
|
/**
|
|
* Stop all of the players at the given time
|
|
* @param {Time} time The time to stop all of the players.
|
|
* @return {Tone.Players} this
|
|
*/
|
|
Tone.Players.prototype.stopAll = function(time) {
|
|
this._forEach(function(player) {
|
|
player.stop(time);
|
|
});
|
|
};
|
|
|
|
/**
|
|
* Dispose and disconnect.
|
|
* @return {Tone.Players} this
|
|
*/
|
|
Tone.Players.prototype.dispose = function() {
|
|
Tone.AudioNode.prototype.dispose.call(this);
|
|
this._volume.dispose();
|
|
this._volume = null;
|
|
this._writable("volume");
|
|
this.volume = null;
|
|
this.output = null;
|
|
this._forEach(function(player) {
|
|
player.dispose();
|
|
});
|
|
this._players = null;
|
|
return this;
|
|
};
|
|
|
|
export default Tone.Players;
|
|
|