mirror of
https://github.com/Tonejs/Tone.js
synced 2024-11-16 16:48:00 +00:00
1026c34163
fixes #330
264 lines
6.8 KiB
JavaScript
264 lines
6.8 KiB
JavaScript
define(["Tone/core/Tone", "Tone/core/Context"], function(Tone){
|
|
|
|
/**
|
|
* @class Tone.AudioNode is the base class for classes which process audio.
|
|
* AudioNodes have inputs and outputs.
|
|
* @param {AudioContext=} context The audio context to use with the class
|
|
* @extends {Tone}
|
|
*/
|
|
Tone.AudioNode = function(){
|
|
Tone.call(this);
|
|
|
|
//use the default context if one is not passed in
|
|
var options = Tone.defaults(arguments, ["context"], {
|
|
"context" : Tone.context
|
|
});
|
|
|
|
/**
|
|
* The AudioContext of this instance
|
|
* @private
|
|
* @type {AudioContext}
|
|
*/
|
|
this._context = options.context;
|
|
};
|
|
|
|
Tone.extend(Tone.AudioNode);
|
|
|
|
/**
|
|
* Get the audio context belonging to this instance.
|
|
* @type {Tone.Context}
|
|
* @memberOf Tone.AudioNode#
|
|
* @name context
|
|
* @readOnly
|
|
*/
|
|
Object.defineProperty(Tone.AudioNode.prototype, "context", {
|
|
get : function(){
|
|
return this._context;
|
|
}
|
|
});
|
|
|
|
/**
|
|
* Create input and outputs for this object.
|
|
* @param {Number} [input=0] The number of inputs
|
|
* @param {Number} [outputs=0] The number of outputs
|
|
* @return {Tone.AudioNode} this
|
|
* @private
|
|
*/
|
|
Tone.AudioNode.prototype.createInsOuts = function(inputs, outputs){
|
|
|
|
if (inputs === 1){
|
|
this.input = this.context.createGain();
|
|
} else if (inputs > 1){
|
|
this.input = new Array(inputs);
|
|
}
|
|
|
|
if (outputs === 1){
|
|
this.output = this.context.createGain();
|
|
} else if (outputs > 1){
|
|
this.output = new Array(outputs);
|
|
}
|
|
};
|
|
|
|
/**
|
|
* channelCount is the number of channels used when up-mixing and down-mixing
|
|
* connections to any inputs to the node. The default value is 2 except for
|
|
* specific nodes where its value is specially determined.
|
|
*
|
|
* @memberof Tone.AudioNode#
|
|
* @type {Number}
|
|
* @name channelCount
|
|
* @readOnly
|
|
*/
|
|
Object.defineProperty(Tone.AudioNode.prototype, "channelCount", {
|
|
get : function(){
|
|
return this.output.channelCount;
|
|
},
|
|
set : function(c){
|
|
return this.output.channelCount = c;
|
|
}
|
|
});
|
|
|
|
/**
|
|
* channelCountMode determines how channels will be counted when up-mixing and
|
|
* down-mixing connections to any inputs to the node.
|
|
* The default value is "max". This attribute has no effect for nodes with no inputs.
|
|
* @memberof Tone.AudioNode#
|
|
* @type {String}
|
|
* @name channelCountMode
|
|
* @readOnly
|
|
*/
|
|
Object.defineProperty(Tone.AudioNode.prototype, "channelCountMode", {
|
|
get : function(){
|
|
return this.output.channelCountMode;
|
|
},
|
|
set : function(m){
|
|
return this.output.channelCountMode = m;
|
|
}
|
|
});
|
|
|
|
/**
|
|
* channelInterpretation determines how individual channels will be treated
|
|
* when up-mixing and down-mixing connections to any inputs to the node.
|
|
* The default value is "speakers".
|
|
* @memberof Tone.AudioNode#
|
|
* @type {String}
|
|
* @name channelInterpretation
|
|
* @readOnly
|
|
*/
|
|
Object.defineProperty(Tone.AudioNode.prototype, "channelInterpretation", {
|
|
get : function(){
|
|
return this.output.channelInterpretation;
|
|
},
|
|
set : function(i){
|
|
return this.output.channelInterpretation = i;
|
|
}
|
|
});
|
|
|
|
/**
|
|
* The number of inputs feeding into the AudioNode.
|
|
* For source nodes, this will be 0.
|
|
* @type {Number}
|
|
* @name numberOfInputs
|
|
* @memberof Tone.AudioNode#
|
|
* @readOnly
|
|
*/
|
|
Object.defineProperty(Tone.AudioNode.prototype, "numberOfInputs", {
|
|
get : function(){
|
|
if (this.input){
|
|
if (Tone.isArray(this.input)){
|
|
return this.input.length;
|
|
} else {
|
|
return 1;
|
|
}
|
|
} else {
|
|
return 0;
|
|
}
|
|
}
|
|
});
|
|
|
|
/**
|
|
* The number of outputs coming out of the AudioNode.
|
|
* @type {Number}
|
|
* @name numberOfOutputs
|
|
* @memberof Tone.AudioNode#
|
|
* @readOnly
|
|
*/
|
|
Object.defineProperty(Tone.AudioNode.prototype, "numberOfOutputs", {
|
|
get : function(){
|
|
if (this.output){
|
|
if (Tone.isArray(this.output)){
|
|
return this.output.length;
|
|
} else {
|
|
return 1;
|
|
}
|
|
} else {
|
|
return 0;
|
|
}
|
|
}
|
|
});
|
|
|
|
/**
|
|
* Called when an audio param connects to this node
|
|
* @private
|
|
*/
|
|
Tone.AudioNode.prototype._onConnect = function(){};
|
|
|
|
/**
|
|
* connect the output of a ToneNode to an AudioParam, AudioNode, or ToneNode
|
|
* @param {Tone | AudioParam | AudioNode} unit
|
|
* @param {number} [outputNum=0] optionally which output to connect from
|
|
* @param {number} [inputNum=0] optionally which input to connect to
|
|
* @returns {Tone.AudioNode} this
|
|
*/
|
|
Tone.AudioNode.prototype.connect = function(unit, outputNum, inputNum){
|
|
if (unit._onConnect){
|
|
unit._onConnect(this);
|
|
}
|
|
if (Tone.isArray(this.output)){
|
|
outputNum = Tone.defaultArg(outputNum, 0);
|
|
this.output[outputNum].connect(unit, 0, inputNum);
|
|
} else {
|
|
this.output.connect(unit, outputNum, inputNum);
|
|
}
|
|
return this;
|
|
};
|
|
|
|
/**
|
|
* disconnect the output
|
|
* @param {Number|AudioNode} output Either the output index to disconnect
|
|
* if the output is an array, or the
|
|
* node to disconnect from.
|
|
* @returns {Tone.AudioNode} this
|
|
*/
|
|
Tone.AudioNode.prototype.disconnect = function(destination, outputNum, inputNum){
|
|
if (Tone.isArray(this.output)){
|
|
if (Tone.isNumber(destination)){
|
|
this.output[destination].disconnect();
|
|
} else {
|
|
outputNum = Tone.defaultArg(outputNum, 0);
|
|
this.output[outputNum].disconnect(destination, 0, inputNum);
|
|
}
|
|
} else {
|
|
this.output.disconnect.apply(this.output, arguments);
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Connect the output of this node to the rest of the nodes in series.
|
|
* @example
|
|
* //connect a node to an effect, panVol and then to the master output
|
|
* node.chain(effect, panVol, Tone.Master);
|
|
* @param {...AudioParam|Tone|AudioNode} nodes
|
|
* @returns {Tone.AudioNode} this
|
|
*/
|
|
Tone.AudioNode.prototype.chain = function(){
|
|
var currentUnit = this;
|
|
for (var i = 0; i < arguments.length; i++){
|
|
var toUnit = arguments[i];
|
|
currentUnit.connect(toUnit);
|
|
currentUnit = toUnit;
|
|
}
|
|
return this;
|
|
};
|
|
|
|
/**
|
|
* connect the output of this node to the rest of the nodes in parallel.
|
|
* @param {...AudioParam|Tone|AudioNode} nodes
|
|
* @returns {Tone.AudioNode} this
|
|
*/
|
|
Tone.AudioNode.prototype.fan = function(){
|
|
for (var i = 0; i < arguments.length; i++){
|
|
this.connect(arguments[i]);
|
|
}
|
|
return this;
|
|
};
|
|
|
|
if (window.AudioNode){
|
|
//give native nodes chain and fan methods
|
|
AudioNode.prototype.chain = Tone.AudioNode.prototype.chain;
|
|
AudioNode.prototype.fan = Tone.AudioNode.prototype.fan;
|
|
}
|
|
|
|
/**
|
|
* Dispose and disconnect
|
|
* @return {Tone.AudioNode} this
|
|
*/
|
|
Tone.AudioNode.prototype.dispose = function(){
|
|
if (Tone.isDefined(this.input)){
|
|
if (this.input instanceof AudioNode){
|
|
this.input.disconnect();
|
|
}
|
|
this.input = null;
|
|
}
|
|
if (Tone.isDefined(this.output)){
|
|
if (this.output instanceof AudioNode){
|
|
this.output.disconnect();
|
|
}
|
|
this.output = null;
|
|
}
|
|
this._context = null;
|
|
return this;
|
|
};
|
|
|
|
return Tone.AudioNode;
|
|
});
|