Tone.Loop provides a simple, schedulable looped callback.

This commit is contained in:
Yotam Mann 2015-11-03 18:37:40 -05:00
parent 03c580db3e
commit a51ed921bf

239
Tone/event/Loop.js Normal file
View file

@ -0,0 +1,239 @@
define(["Tone/core/Tone", "Tone/event/Event"], function (Tone) {
/**
* @class Tone.Loop creates a looped callback at the
* specified interval. The callback can be
* started, stopped and scheduled along
* the Transport's timeline.
* @example
* var loop = new Tone.Loop(function(time){
* //triggered every eighth note.
* console.log(time);
* }, "8n").start(0);
* Tone.Transport.start();
* @extends {Tone}
* @param {Function} callback The callback to invoke with the
* event.
* @param {Array} events The events to arpeggiate over.
*/
Tone.Loop = function(){
var options = this.optionsObject(arguments, ["callback", "interval"], Tone.Loop.defaults);
/**
* The event which produces the callbacks
*/
this._event = new Tone.Event({
"callback" : this._tick.bind(this),
"loop" : true,
"loopEnd" : options.interval,
"playbackRate" : options.playbackRate,
"probability" : options.probability
});
/**
* The callback to invoke with the next event in the pattern
* @type {Function}
*/
this.callback = options.callback;
//set the iterations
this.iterations = options.iterations;
};
Tone.extend(Tone.Loop);
/**
* The defaults
* @const
* @type {Object}
*/
Tone.Loop.defaults = {
"interval" : "4n",
"callback" : Tone.noOp,
"playbackRate" : 1,
"iterations" : Infinity,
"probability" : true,
"mute" : false
};
/**
* Start the loop at the specified time along the Transport's
* timeline.
* @param {Time=} time When to start the Loop.
* @return {Tone.Loop} this
*/
Tone.Loop.prototype.start = function(time){
this._event.start(time);
return this;
};
/**
* Stop the arpeggio at the given time.
* @param {Time=} time When to stop the Arpeggio
* @return {Tone.Loop} this
*/
Tone.Loop.prototype.stop = function(time){
this._event.stop(time);
return this;
};
/**
* Cancel all scheduled events greater than or equal to the given time
* @param {Time} [time=0] The time after which events will be cancel.
* @return {Tone.Loop} this
*/
Tone.Loop.prototype.cancel = function(time){
this._event.cancel(time);
return this;
};
/**
* Internal function called when the notes should be called
* @param {Number} time The time the event occurs
* @private
*/
Tone.Loop.prototype._tick = function(time){
this.callback(time);
};
/**
* The state of the Loop, either started or stopped.
* @memberOf Tone.Loop#
* @type {String}
* @name state
* @readOnly
*/
Object.defineProperty(Tone.Loop.prototype, "state", {
get : function(){
return this._event.state;
}
});
/**
* The progress of the loop as a value between 0-1. 0, when
* the loop is stopped or done iterating.
* @memberOf Tone.Loop#
* @type {NormalRange}
* @name progress
* @readOnly
*/
Object.defineProperty(Tone.Loop.prototype, "progress", {
get : function(){
return this._event.progress;
}
});
/**
* The repeat interval
* @memberOf Tone.Loop#
* @type {Time}
* @name interval
*/
Object.defineProperty(Tone.Loop.prototype, "interval", {
get : function(){
return this._event.loopEnd;
},
set : function(interval){
this._event.loopEnd = interval;
}
});
/**
* The playback rate of the pattern.
* @memberOf Tone.Loop#
* @type {Time}
* @name playbackRate
*/
Object.defineProperty(Tone.Loop.prototype, "playbackRate", {
get : function(){
return this._event.playbackRate;
},
set : function(rate){
this._event.playbackRate = rate;
}
});
/**
* Random variation +/-0.01s to the scheduled time.
* Or give it a time value which it will randomize by.
* @type {Boolean|Time}
* @memberOf Tone.Loop#
* @name humanize
*/
Object.defineProperty(Tone.Loop.prototype, "humanize", {
get : function(){
return this._event.humanize;
},
set : function(variation){
this._event.humanize = variation;
}
});
/**
* The probably of the callback being invoked.
* @memberOf Tone.Loop#
* @type {NormalRange}
* @name probability
*/
Object.defineProperty(Tone.Loop.prototype, "probability", {
get : function(){
return this._event.probability;
},
set : function(prob){
this._event.probability = prob;
}
});
/**
* Muting the Loop means that no callbacks are invoked.
* @memberOf Tone.Loop#
* @type {Boolean}
* @name mute
*/
Object.defineProperty(Tone.Loop.prototype, "mute", {
get : function(){
return this._event.mute;
},
set : function(mute){
this._event.mute = mute;
}
});
/**
* The number of iterations of the loop. The default
* value is Infinity (loop forever).
* @memberOf Tone.Loop#
* @type {Positive}
* @name iterations
*/
Object.defineProperty(Tone.Loop.prototype, "iterations", {
get : function(){
if (this._event.loop === true){
return Infinity;
} else {
return this._event.loop;
}
return this._pattern.index;
},
set : function(iters){
if (iters === Infinity){
this._event.loop = true;
} else {
this._event.loop = iters;
}
}
});
/**
* Clean up
* @return {Tone.Loop} this
*/
Tone.Loop.prototype.dispose = function(){
this._event.dispose();
this._event = null;
this.callback = null;
};
return Tone.Loop;
});