2016-12-19 01:26:11 +00:00
|
|
|
define(["Tone/core/Tone", "Tone/core/Timeline"], function (Tone) {
|
|
|
|
|
|
|
|
"use strict";
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @class Tone.Draw is useful for synchronizing visuals and audio events.
|
|
|
|
* Callbacks from Tone.Transport or any of the Tone.Event classes
|
|
|
|
* always happen _before_ the scheduled time and are not synchronized
|
|
|
|
* to the animation frame so they are not good for triggering tightly
|
|
|
|
* synchronized visuals and sound. Tone.Draw makes it easy to schedule
|
|
|
|
* callbacks using the AudioContext time and uses requestAnimationFrame.
|
|
|
|
*
|
|
|
|
* @singleton
|
|
|
|
* @extends {Tone}
|
|
|
|
* @example
|
|
|
|
* Tone.Transport.schedule(function(time){
|
|
|
|
* //use the time argument to schedule a callback with Tone.Draw
|
|
|
|
* Tone.Draw.schedule(function(){
|
|
|
|
* //do drawing or DOM manipulation here
|
|
|
|
* }, time)
|
|
|
|
* }, "+0.5")
|
|
|
|
*/
|
|
|
|
Tone.Draw = function(){
|
2017-04-25 03:23:15 +00:00
|
|
|
|
|
|
|
Tone.call(this);
|
|
|
|
|
2016-12-19 01:26:11 +00:00
|
|
|
/**
|
|
|
|
* All of the events.
|
|
|
|
* @type {Tone.Timeline}
|
|
|
|
* @private
|
|
|
|
*/
|
|
|
|
this._events = new Tone.Timeline();
|
|
|
|
|
|
|
|
/**
|
2016-12-28 23:39:24 +00:00
|
|
|
* The duration after which events are not invoked.
|
2016-12-19 01:26:11 +00:00
|
|
|
* @type {Number}
|
2016-12-28 23:39:24 +00:00
|
|
|
* @default 0.25
|
2016-12-19 01:26:11 +00:00
|
|
|
*/
|
|
|
|
this.expiration = 0.25;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* The amount of time before the scheduled time
|
|
|
|
* that the callback can be invoked. Default is
|
|
|
|
* half the time of an animation frame (0.008 seconds).
|
|
|
|
* @type {Number}
|
2016-12-28 23:39:24 +00:00
|
|
|
* @default 0.008
|
2016-12-19 01:26:11 +00:00
|
|
|
*/
|
|
|
|
this.anticipation = 0.008;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* The draw loop
|
|
|
|
* @type {Function}
|
|
|
|
* @private
|
|
|
|
*/
|
|
|
|
this._boundDrawLoop = this._drawLoop.bind(this);
|
|
|
|
};
|
|
|
|
|
|
|
|
Tone.extend(Tone.Draw);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Schedule a function at the given time to be invoked
|
|
|
|
* on the nearest animation frame.
|
|
|
|
* @param {Function} callback Callback is invoked at the given time.
|
|
|
|
* @param {Time} time The time relative to the AudioContext time
|
|
|
|
* to invoke the callback.
|
|
|
|
* @return {Tone.Draw} this
|
|
|
|
*/
|
|
|
|
Tone.Draw.prototype.schedule = function(callback, time){
|
2016-12-19 02:56:22 +00:00
|
|
|
this._events.add({
|
2016-12-19 01:26:11 +00:00
|
|
|
callback : callback,
|
|
|
|
time : this.toSeconds(time)
|
|
|
|
});
|
2017-02-08 03:26:08 +00:00
|
|
|
//start the draw loop on the first event
|
|
|
|
if (this._events.length === 1){
|
|
|
|
requestAnimationFrame(this._boundDrawLoop);
|
|
|
|
}
|
2016-12-19 01:26:11 +00:00
|
|
|
return this;
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Cancel events scheduled after the given time
|
|
|
|
* @param {Time=} after Time after which scheduled events will
|
|
|
|
* be removed from the scheduling timeline.
|
|
|
|
* @return {Tone.Draw} this
|
|
|
|
*/
|
|
|
|
Tone.Draw.prototype.cancel = function(after){
|
|
|
|
this._events.cancel(this.toSeconds(after));
|
|
|
|
return this;
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* The draw loop
|
|
|
|
* @private
|
|
|
|
*/
|
|
|
|
Tone.Draw.prototype._drawLoop = function(){
|
|
|
|
var now = Tone.now();
|
|
|
|
while(this._events.length && this._events.peek().time - this.anticipation <= now){
|
|
|
|
var event = this._events.shift();
|
|
|
|
if (now - event.time <= this.expiration){
|
|
|
|
event.callback();
|
|
|
|
}
|
|
|
|
}
|
2017-02-08 03:26:08 +00:00
|
|
|
if (this._events.length > 0){
|
|
|
|
requestAnimationFrame(this._boundDrawLoop);
|
|
|
|
}
|
2016-12-19 01:26:11 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
//make a singleton
|
|
|
|
Tone.Draw = new Tone.Draw();
|
|
|
|
|
|
|
|
return Tone.Draw;
|
|
|
|
});
|