mirror of
https://github.com/Tonejs/Tone.js
synced 2024-11-16 08:38:00 +00:00
refactored out clock from Transport
This commit is contained in:
parent
23e49f54f2
commit
cd4388fe89
2 changed files with 290 additions and 144 deletions
146
Tone/core/Clock.js
Normal file
146
Tone/core/Clock.js
Normal file
|
@ -0,0 +1,146 @@
|
|||
define(["Tone/core/Tone", "Tone/signal/Signal"], function(Tone){
|
||||
|
||||
/**
|
||||
* @class a sample accurate clock built on an oscillator.
|
||||
* Invokes the onTick method at the set rate
|
||||
* NB: can cause audio glitches. use sparingly.
|
||||
*
|
||||
* @internal
|
||||
* @constructor
|
||||
* @extends {Tone}
|
||||
* @param {number} rate the number of
|
||||
*/
|
||||
Tone.Clock = function(rate, callback){
|
||||
|
||||
/**
|
||||
* the oscillator
|
||||
* @type {OscillatorNode}
|
||||
*/
|
||||
this._oscillator = null;
|
||||
|
||||
/**
|
||||
* the script processor which listens to the oscillator
|
||||
* @type {[type]}
|
||||
* @private
|
||||
*/
|
||||
this._jsNode = this.context.createScriptProcessor(this.bufferSize, 1, 1);
|
||||
this._jsNode.onaudioprocess = this._processBuffer.bind(this);
|
||||
|
||||
/**
|
||||
* the rate control signal
|
||||
* @type {Tone.Signal}
|
||||
* @private
|
||||
*/
|
||||
this._controlSignal = new Tone.Signal(1);
|
||||
|
||||
/**
|
||||
* whether the tick is on the up or down
|
||||
* @type {boolean}
|
||||
* @private
|
||||
*/
|
||||
this._upTick = false;
|
||||
|
||||
/**
|
||||
* the callback which is invoked on every tick
|
||||
* with the time of that tick as the argument
|
||||
* @type {function(number)}
|
||||
*/
|
||||
this.tick = this.defaultArg(callback, function(){});
|
||||
|
||||
//setup
|
||||
this._jsNode.noGC();
|
||||
this.setRate(rate);
|
||||
};
|
||||
|
||||
Tone.extend(Tone.Clock);
|
||||
|
||||
/**
|
||||
* set the rate of the clock
|
||||
* optionally ramp to the rate over the rampTime
|
||||
* @param {Tone.Time} rate
|
||||
* @param {Tone.Time=} rampTime
|
||||
*/
|
||||
Tone.Clock.prototype.setRate = function(rate, rampTime){
|
||||
//convert the time to a to frequency
|
||||
var freqVal = this.secondsToFrequency(this.toSeconds(rate));
|
||||
if (!rampTime){
|
||||
this._controlSignal.cancelScheduledValues(0);
|
||||
this._controlSignal.setValue(freqVal);
|
||||
} else {
|
||||
this._controlSignal.exponentialRampToValueNow(freqVal, rampTime);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* return the current rate
|
||||
*
|
||||
* @return {number}
|
||||
*/
|
||||
Tone.Clock.prototype.getRate = function(){
|
||||
return this._controlSignal.getValue();
|
||||
};
|
||||
|
||||
/**
|
||||
* start the clock
|
||||
* @param {Tone.Time} time the time when the clock should start
|
||||
*/
|
||||
Tone.Clock.prototype.start = function(time){
|
||||
//reset the oscillator
|
||||
this._oscillator = this.context.createOscillator();
|
||||
this._oscillator.type = "square";
|
||||
this._oscillator.connect(this._jsNode);
|
||||
//connect it up
|
||||
this._controlSignal.connect(this._oscillator.frequency);
|
||||
this._oscillator.frequency.value = 0;
|
||||
this._upTick = false;
|
||||
var startTime = this.toSeconds(time);
|
||||
this._oscillator.start(startTime);
|
||||
};
|
||||
|
||||
/**
|
||||
* stop the clock
|
||||
* @param {Tone.Time} time the time when the clock should stop
|
||||
*/
|
||||
Tone.Clock.prototype.stop = function(time){
|
||||
var stopTime = this.toSeconds(time);
|
||||
this._oscillator.stop(stopTime);
|
||||
};
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {AudioProcessingEvent} event
|
||||
*/
|
||||
Tone.Clock.prototype._processBuffer = function(event){
|
||||
var now = this.defaultArg(event.playbackTime, this.now());
|
||||
var bufferSize = this._jsNode.bufferSize;
|
||||
var incomingBuffer = event.inputBuffer.getChannelData(0);
|
||||
var upTick = this._upTick;
|
||||
for (var i = 0; i < bufferSize; i++){
|
||||
var sample = incomingBuffer[i];
|
||||
if (sample > 0 && !upTick){
|
||||
upTick = true;
|
||||
this.tick(now + this.samplesToSeconds(i));
|
||||
} else if (sample < 0 && upTick){
|
||||
upTick = false;
|
||||
}
|
||||
}
|
||||
this._upTick = upTick;
|
||||
};
|
||||
|
||||
/**
|
||||
* clean up
|
||||
*/
|
||||
Tone.Clock.prototype.dispose = function(){
|
||||
this._jsNode.disconnect();
|
||||
this._controlSignal.dispose();
|
||||
if (this._oscillator){
|
||||
this._oscillator.disconnect();
|
||||
}
|
||||
this._jsNode.onaudioprocess = function(){};
|
||||
this._jsNode = null;
|
||||
this._controlSignal = null;
|
||||
this._oscillator = null;
|
||||
};
|
||||
|
||||
return Tone.Clock;
|
||||
});
|
|
@ -1,23 +1,23 @@
|
|||
define(["Tone/core/Tone", "Tone/core/Master", "Tone/signal/Signal"],
|
||||
define(["Tone/core/Tone", "Tone/core/Clock", "Tone/signal/Signal"],
|
||||
function(Tone){
|
||||
|
||||
/**
|
||||
* oscillator-based transport allows for simple musical timing
|
||||
* supports tempo curves and time changes
|
||||
* @class oscillator-based transport allows for simple musical timing
|
||||
* supports tempo curves and time changes
|
||||
*
|
||||
* @constructor
|
||||
* @extends {Tone}
|
||||
*/
|
||||
Tone.Transport = function(){
|
||||
var Transport = function(){
|
||||
|
||||
/**
|
||||
* watches the main oscillator for timing ticks
|
||||
* initially starts at 120bpm
|
||||
*
|
||||
* @private
|
||||
* @type {ScriptProcessorNode}
|
||||
* @type {Tone.Clock}
|
||||
*/
|
||||
this._jsNode = this.context.createScriptProcessor(this.bufferSize, 1, 1);
|
||||
this._jsNode.onaudioprocess = this._processBuffer.bind(this);
|
||||
this._clock = new Tone.Clock(1, this._processTick.bind(this));
|
||||
|
||||
/**
|
||||
* @type {boolean}
|
||||
|
@ -28,33 +28,28 @@ function(Tone){
|
|||
* @type {TransportState}
|
||||
*/
|
||||
this.state = TransportState.STOPPED;
|
||||
|
||||
//so it doesn't get garbage collected
|
||||
this._jsNode.noGC();
|
||||
};
|
||||
|
||||
Tone.extend(Tone.Transport);
|
||||
Tone.extend(Transport);
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {number}
|
||||
*/
|
||||
var timelineTicks = 0;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {number}
|
||||
*/
|
||||
var transportTicks = 0;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {number}
|
||||
*/
|
||||
var tatum = 12;
|
||||
/**
|
||||
* @private
|
||||
* @type {Boolean}
|
||||
*/
|
||||
var upTick = false;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {number}
|
||||
|
@ -96,22 +91,6 @@ function(Tone){
|
|||
*/
|
||||
var timelineProgress = 0;
|
||||
|
||||
/**
|
||||
* The main oscillator for the system
|
||||
* @private
|
||||
* @type {OscillatorNode}
|
||||
*/
|
||||
var oscillator = null;
|
||||
|
||||
/**
|
||||
* controls the oscillator frequency
|
||||
* starts at 120bpm
|
||||
*
|
||||
* @private
|
||||
* @type {Tone.Signal}
|
||||
*/
|
||||
var controlSignal = new Tone.Signal(24);
|
||||
|
||||
/**
|
||||
* All of the synced components
|
||||
* @private
|
||||
|
@ -119,7 +98,6 @@ function(Tone){
|
|||
*/
|
||||
var SyncedSources = [];
|
||||
|
||||
|
||||
/**
|
||||
* @enum
|
||||
*/
|
||||
|
@ -129,49 +107,36 @@ function(Tone){
|
|||
STOPPED : "stopped"
|
||||
};
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// JS NODE PROCESSING
|
||||
// TICKS
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* called when a buffer is ready
|
||||
*
|
||||
* @param {AudioProcessingEvent} event
|
||||
* called on every tick
|
||||
* @param {number} tickTime clock relative tick time
|
||||
* @private
|
||||
*/
|
||||
Tone.Transport.prototype._processBuffer = function(event){
|
||||
var now = this.defaultArg(event.playbackTime, this.now());
|
||||
var bufferSize = this._jsNode.bufferSize;
|
||||
var incomingBuffer = event.inputBuffer.getChannelData(0);
|
||||
for (var i = 0; i < bufferSize; i++){
|
||||
var sample = incomingBuffer[i];
|
||||
if (sample > 0 && !upTick){
|
||||
upTick = true;
|
||||
this._processTick(now + this.samplesToSeconds(i));
|
||||
} else if (sample < 0 && upTick){
|
||||
upTick = false;
|
||||
Transport.prototype._processTick = function(tickTime){
|
||||
processIntervals(tickTime);
|
||||
processTimeouts(tickTime);
|
||||
processTimeline(tickTime);
|
||||
transportTicks += 1;
|
||||
timelineTicks += 1;
|
||||
if (this.loop){
|
||||
if (timelineTicks === loopEnd){
|
||||
this._setTicks(loopStart);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
//@param {number} tickTime
|
||||
Tone.Transport.prototype._processTick = function(tickTime){
|
||||
if (oscillator !== null){
|
||||
processIntervals(tickTime);
|
||||
processTimeouts(tickTime);
|
||||
processTimeline(tickTime);
|
||||
transportTicks += 1;
|
||||
timelineTicks += 1;
|
||||
if (this.loop){
|
||||
if (timelineTicks === loopEnd){
|
||||
this._setTicks(loopStart);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
//jump to a specific tick in the timeline
|
||||
Tone.Transport.prototype._setTicks = function(ticks){
|
||||
/**
|
||||
* jump to a specific tick in the timeline
|
||||
* updates the timeline callbacks
|
||||
*
|
||||
* @param {number} ticks the tick to jump to
|
||||
* @private
|
||||
*/
|
||||
Transport.prototype._setTicks = function(ticks){
|
||||
timelineTicks = ticks;
|
||||
for (var i = 0; i < transportTimeline.length; i++){
|
||||
var timeout = transportTimeline[i];
|
||||
|
@ -236,14 +201,6 @@ function(Tone){
|
|||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* clear the timeouts and intervals
|
||||
*/
|
||||
function clearTimelineEvents(){
|
||||
|
||||
intervals = [];
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// INTERVAL
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -256,7 +213,7 @@ function(Tone){
|
|||
* @param {Object} ctx the context the function is invoked in
|
||||
* @return {number} the id of the interval
|
||||
*/
|
||||
Tone.Transport.prototype.setInterval = function(callback, interval, ctx){
|
||||
Transport.prototype.setInterval = function(callback, interval, ctx){
|
||||
var tickTime = this.toTicks(interval);
|
||||
var timeout = new TimelineEvent(callback, ctx, tickTime, transportTicks);
|
||||
intervals.push(timeout);
|
||||
|
@ -268,7 +225,7 @@ function(Tone){
|
|||
* @param {number} rmInterval the interval to remove
|
||||
* @return {boolean} true if the event was removed
|
||||
*/
|
||||
Tone.Transport.prototype.clearInterval = function(rmInterval){
|
||||
Transport.prototype.clearInterval = function(rmInterval){
|
||||
for (var i = 0; i < intervals.length; i++){
|
||||
var interval = intervals[i];
|
||||
if (interval.id === rmInterval){
|
||||
|
@ -282,7 +239,7 @@ function(Tone){
|
|||
/**
|
||||
* removes all of the intervals that are currently set
|
||||
*/
|
||||
Tone.Transport.prototype.clearIntervals = function(){
|
||||
Transport.prototype.clearIntervals = function(){
|
||||
intervals = [];
|
||||
};
|
||||
|
||||
|
@ -298,7 +255,7 @@ function(Tone){
|
|||
* @param {Object} ctx the context to invoke the callback in
|
||||
* @return {number} the id of the timeout for clearing timeouts
|
||||
*/
|
||||
Tone.Transport.prototype.setTimeout = function(callback, time, ctx){
|
||||
Transport.prototype.setTimeout = function(callback, time, ctx){
|
||||
var ticks = this.toTicks(time);
|
||||
var timeout = new TimelineEvent(callback, ctx, ticks + transportTicks, 0);
|
||||
//put it in the right spot
|
||||
|
@ -319,7 +276,7 @@ function(Tone){
|
|||
* @param {number} timeoutID
|
||||
* @return {boolean} true if the timeout was removed
|
||||
*/
|
||||
Tone.Transport.prototype.clearTimeout = function(timeoutID){
|
||||
Transport.prototype.clearTimeout = function(timeoutID){
|
||||
for (var i = 0; i < timeouts.length; i++){
|
||||
var testTimeout = timeouts[i];
|
||||
if (testTimeout.id === timeoutID){
|
||||
|
@ -335,7 +292,7 @@ function(Tone){
|
|||
*
|
||||
* @todo (optionally) remove events after a certain time
|
||||
*/
|
||||
Tone.Transport.prototype.clearTimeouts = function(){
|
||||
Transport.prototype.clearTimeouts = function(){
|
||||
timeouts = [];
|
||||
};
|
||||
|
||||
|
@ -354,7 +311,7 @@ function(Tone){
|
|||
* @param {Object} ctx the context in which the funtion is called
|
||||
* @return {number} the id for clearing the transportTimeline event
|
||||
*/
|
||||
Tone.Transport.prototype.setTimeline = function(callback, timeout, ctx){
|
||||
Transport.prototype.setTimeline = function(callback, timeout, ctx){
|
||||
var ticks = this.toTicks(timeout);
|
||||
var timelineEvnt = new TimelineEvent(callback, ctx, ticks, 0);
|
||||
//put it in the right spot
|
||||
|
@ -375,7 +332,7 @@ function(Tone){
|
|||
* @param {number} timelineID
|
||||
* @return {boolean} true if it was removed
|
||||
*/
|
||||
Tone.Transport.prototype.clearTimeline = function(timelineID){
|
||||
Transport.prototype.clearTimeline = function(timelineID){
|
||||
for (var i = 0; i < transportTimeline.length; i++){
|
||||
var testTimeline = transportTimeline[i];
|
||||
if (testTimeline.id === timelineID){
|
||||
|
@ -389,7 +346,7 @@ function(Tone){
|
|||
/**
|
||||
* remove all events from the timeline
|
||||
*/
|
||||
Tone.Transport.prototype.clearTimelines = function(){
|
||||
Transport.prototype.clearTimelines = function(){
|
||||
timelineProgress = 0;
|
||||
transportTimeline = [];
|
||||
};
|
||||
|
@ -403,7 +360,7 @@ function(Tone){
|
|||
* @param {Tone.Time} time
|
||||
* @return {number}
|
||||
*/
|
||||
Tone.Transport.prototype.toTicks = function(time){
|
||||
Transport.prototype.toTicks = function(time){
|
||||
//get the seconds
|
||||
var seconds = this.toSeconds(time);
|
||||
var quarter = this.notationToSeconds("4n");
|
||||
|
@ -417,7 +374,7 @@ function(Tone){
|
|||
* get the transport time
|
||||
* @return {string} in transportTime format (measures:beats:sixteenths)
|
||||
*/
|
||||
Tone.Transport.prototype.getTransportTime = function(){
|
||||
Transport.prototype.getTransportTime = function(){
|
||||
var quarters = timelineTicks / tatum;
|
||||
var measures = Math.floor(quarters / transportTimeSignature);
|
||||
var sixteenths = Math.floor((quarters % 1) * 4);
|
||||
|
@ -431,7 +388,7 @@ function(Tone){
|
|||
*
|
||||
* @param {Tone.Time} progress
|
||||
*/
|
||||
Tone.Transport.prototype.setTransportTime = function(progress){
|
||||
Transport.prototype.setTransportTime = function(progress){
|
||||
var ticks = this.toTicks(progress);
|
||||
this._setTicks(ticks);
|
||||
};
|
||||
|
@ -445,20 +402,11 @@ function(Tone){
|
|||
*
|
||||
* @param {Tone.Time} time
|
||||
*/
|
||||
Tone.Transport.prototype.start = function(time){
|
||||
Transport.prototype.start = function(time){
|
||||
if (this.state === TransportState.STOPPED || this.state === TransportState.PAUSED){
|
||||
this.state = TransportState.STARTED;
|
||||
//reset the oscillator
|
||||
oscillator = this.context.createOscillator();
|
||||
oscillator.type = "square";
|
||||
oscillator.connect(this._jsNode);
|
||||
//connect it up
|
||||
controlSignal.connect(oscillator.frequency);
|
||||
oscillator.frequency.value = 0;
|
||||
upTick = false;
|
||||
|
||||
var startTime = this.toSeconds(time);
|
||||
oscillator.start(startTime);
|
||||
this._clock.start(startTime);
|
||||
//call start on each of the synced sources
|
||||
for (var i = 0; i < SyncedSources.length; i++){
|
||||
var source = SyncedSources[i].source;
|
||||
|
@ -474,16 +422,13 @@ function(Tone){
|
|||
*
|
||||
* @param {Tone.Time} time
|
||||
*/
|
||||
Tone.Transport.prototype.stop = function(time){
|
||||
Transport.prototype.stop = function(time){
|
||||
if (this.state === TransportState.STARTED || this.state === TransportState.PAUSED){
|
||||
this.state = TransportState.STOPPED;
|
||||
var stopTime = this.toSeconds(time);
|
||||
oscillator.stop(stopTime);
|
||||
oscillator = null;
|
||||
this._clock.stop(stopTime);
|
||||
this._setTicks(0);
|
||||
this.clearTimeouts();
|
||||
this.clearIntervals();
|
||||
|
||||
//call start on each of the synced sources
|
||||
for (var i = 0; i < SyncedSources.length; i++){
|
||||
var source = SyncedSources[i].source;
|
||||
|
@ -497,13 +442,11 @@ function(Tone){
|
|||
*
|
||||
* @param {Tone.Time} time
|
||||
*/
|
||||
Tone.Transport.prototype.pause = function(time){
|
||||
Transport.prototype.pause = function(time){
|
||||
if (this.state === TransportState.STARTED){
|
||||
this.state = TransportState.PAUSED;
|
||||
var stopTime = this.toSeconds(time);
|
||||
oscillator.stop(stopTime);
|
||||
oscillator = null;
|
||||
clearTimelineEvents();
|
||||
this._clock.stop(stopTime);
|
||||
//call pause on each of the synced sources
|
||||
for (var i = 0; i < SyncedSources.length; i++){
|
||||
var source = SyncedSources[i].source;
|
||||
|
@ -522,17 +465,9 @@ function(Tone){
|
|||
* @param {number} bpm
|
||||
* @param {Tone.Time=} rampTime
|
||||
*/
|
||||
Tone.Transport.prototype.setBpm = function(bpm, rampTime){
|
||||
//convert the bpm to frequency
|
||||
var tatumFreq = this.secondsToFrequency(this.notationToSeconds(tatum.toString() + "n", bpm, transportTimeSignature));
|
||||
// var tatumFreq = this.toFrequency(tatum.toString() + "n", bpm, transportTimeSignature);
|
||||
var freqVal = 4 * tatumFreq;
|
||||
if (!rampTime){
|
||||
controlSignal.cancelScheduledValues(0);
|
||||
controlSignal.setValue(freqVal);
|
||||
} else {
|
||||
controlSignal.exponentialRampToValueNow(freqVal, rampTime);
|
||||
}
|
||||
Transport.prototype.setBpm = function(bpm, rampTime){
|
||||
var quarterTime = this.notationToSeconds(tatum.toString() + "n", bpm, transportTimeSignature) / 4;
|
||||
this._clock.setRate(quarterTime, rampTime);
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -540,9 +475,9 @@ function(Tone){
|
|||
*
|
||||
* @return {number}
|
||||
*/
|
||||
Tone.Transport.prototype.getBpm = function(){
|
||||
Transport.prototype.getBpm = function(){
|
||||
//convert the current frequency of the oscillator to bpm
|
||||
var freq = controlSignal.getValue();
|
||||
var freq = this._clock.getRate();
|
||||
return 60 * (freq / tatum);
|
||||
};
|
||||
|
||||
|
@ -555,7 +490,7 @@ function(Tone){
|
|||
* @param {number} numerator
|
||||
* @param {number=} denominator defaults to 4
|
||||
*/
|
||||
Tone.Transport.prototype.setTimeSignature = function(numerator, denominator){
|
||||
Transport.prototype.setTimeSignature = function(numerator, denominator){
|
||||
denominator = this.defaultArg(denominator, 4);
|
||||
transportTimeSignature = numerator / (denominator / 4);
|
||||
};
|
||||
|
@ -567,7 +502,7 @@ function(Tone){
|
|||
*
|
||||
* @return {number}
|
||||
*/
|
||||
Tone.Transport.prototype.getTimeSignature = function(){
|
||||
Transport.prototype.getTimeSignature = function(){
|
||||
return transportTimeSignature;
|
||||
};
|
||||
|
||||
|
@ -576,7 +511,7 @@ function(Tone){
|
|||
*
|
||||
* @param {Tone.Time} startPosition
|
||||
*/
|
||||
Tone.Transport.prototype.setLoopStart = function(startPosition){
|
||||
Transport.prototype.setLoopStart = function(startPosition){
|
||||
loopStart = this.toTicks(startPosition);
|
||||
};
|
||||
|
||||
|
@ -585,7 +520,7 @@ function(Tone){
|
|||
*
|
||||
* @param {Tone.Time} endPosition
|
||||
*/
|
||||
Tone.Transport.prototype.setLoopEnd = function(endPosition){
|
||||
Transport.prototype.setLoopEnd = function(endPosition){
|
||||
loopEnd = this.toTicks(endPosition);
|
||||
};
|
||||
|
||||
|
@ -594,7 +529,7 @@ function(Tone){
|
|||
* @param {Tone.Time} startPosition
|
||||
* @param {Tone.Time} endPosition
|
||||
*/
|
||||
Tone.Transport.prototype.setLoopPoint = function(startPosition, endPosition){
|
||||
Transport.prototype.setLoopPoint = function(startPosition, endPosition){
|
||||
this.setLoopStart(startPosition);
|
||||
this.setLoopEnd(endPosition);
|
||||
};
|
||||
|
@ -609,13 +544,26 @@ function(Tone){
|
|||
* @param {Tone.Source} source the source to sync to the transport
|
||||
* @param {Tone.Time} delay (optionally) start the source with a delay from the transport
|
||||
*/
|
||||
Tone.Transport.prototype.sync = function(source, startDelay){
|
||||
Transport.prototype.syncSource = function(source, startDelay){
|
||||
SyncedSources.push({
|
||||
source : source,
|
||||
delay : this.toSeconds(this.defaultArg(startDelay, 0))
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* remove the source from the list of Synced Sources
|
||||
*
|
||||
* @param {Tone.Source} source [description]
|
||||
*/
|
||||
Transport.prototype.unsyncSource = function(source){
|
||||
for (var i = 0; i < SyncedSources.length; i++){
|
||||
if (SyncedSources[i].source === source){
|
||||
SyncedSources.splice(i, 1);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* attaches the signal to the tempo control signal so that
|
||||
* any changes in the tempo will change the signal in the same
|
||||
|
@ -623,24 +571,10 @@ function(Tone){
|
|||
*
|
||||
* @param {Tone.Signal} signal
|
||||
*/
|
||||
Tone.Transport.prototype.syncSignal = function(signal){
|
||||
Transport.prototype.syncSignal = function(signal){
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* remove the source from the list of Synced Sources
|
||||
*
|
||||
* @param {Tone.Source} source [description]
|
||||
*/
|
||||
Tone.Transport.prototype.unsync = function(source){
|
||||
for (var i = 0; i < SyncedSources.length; i++){
|
||||
if (SyncedSources[i].source === source){
|
||||
SyncedSources.splice(i, 1);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// TIMELINE EVENT
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -655,6 +589,7 @@ function(Tone){
|
|||
* A Timeline event
|
||||
*
|
||||
* @constructor
|
||||
* @internal
|
||||
* @param {function(number)} callback
|
||||
* @param {Object} context
|
||||
* @param {number} tickTime
|
||||
|
@ -698,6 +633,15 @@ function(Tone){
|
|||
};
|
||||
|
||||
|
||||
/**
|
||||
* clean up
|
||||
*/
|
||||
Transport.prototype.dispose = function(){
|
||||
this._clock.dispose();
|
||||
this._clock = null;
|
||||
};
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// AUGMENT TONE'S PROTOTYPE TO INCLUDE TRANSPORT TIMING
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -720,6 +664,19 @@ function(Tone){
|
|||
};
|
||||
})();
|
||||
|
||||
/**
|
||||
* tests if a string is in Tick notation
|
||||
* @return {boolean}
|
||||
* @method isTicks
|
||||
* @lends Tone.prototype.isNotation
|
||||
*/
|
||||
Tone.prototype.isTicks = (function(){
|
||||
var tickFormat = new RegExp(/[0-9]+[i]$/i);
|
||||
return function(tick){
|
||||
return tickFormat.test(tick);
|
||||
};
|
||||
})();
|
||||
|
||||
/**
|
||||
* tests if a string is transportTime
|
||||
* i.e. :
|
||||
|
@ -819,6 +776,19 @@ function(Tone){
|
|||
return beats * this.notationToSeconds("4n");
|
||||
};
|
||||
|
||||
/**
|
||||
* convert ticks into seconds
|
||||
* @param {string} transportTime
|
||||
* @param {number=} bpm
|
||||
* @param {number=} timeSignature
|
||||
* @return {number} seconds
|
||||
*/
|
||||
Tone.prototype.ticksToSeconds = function(ticks, bpm, timeSignature){
|
||||
ticks = parseInt(ticks);
|
||||
var measure = this.notationToSeconds("4n", bpm, timeSignature);
|
||||
return (measure * 4) / (tatum / ticks);
|
||||
};
|
||||
|
||||
/**
|
||||
* Convert seconds to the closest transportTime in the form
|
||||
* measures:quarters:sixteenths
|
||||
|
@ -867,6 +837,13 @@ function(Tone){
|
|||
* unlike the method which it overrides, this takes into account
|
||||
* transporttime and musical notation
|
||||
*
|
||||
* Time : 1.40
|
||||
* Notation: 4n|1m|2t
|
||||
* TransportTime: 2:4:1 (measure:quarters:sixteens)
|
||||
* Now Relative: +3n
|
||||
* Math: 3n+16n or even very complicated expressions ((3n*2)/6 + 1)
|
||||
* Ticks: "146i"
|
||||
*
|
||||
* @override
|
||||
* @param {Tone.Time} time
|
||||
* @param {number=} now if passed in, this number will be
|
||||
|
@ -883,7 +860,24 @@ function(Tone){
|
|||
plusTime = now;
|
||||
time = time.slice(1);
|
||||
}
|
||||
if (this.isNotation(time)){
|
||||
var components = time.split(/[\(\)\-\+\/\*]/);
|
||||
if (components.length > 1){
|
||||
var oringalTime = time;
|
||||
for(var i = 0; i < components.length; i++){
|
||||
var symb = components[i];
|
||||
if (symb !== ""){
|
||||
var val = this.toSeconds(symb.trim());
|
||||
time = time.replace(symb, val);
|
||||
}
|
||||
}
|
||||
try {
|
||||
//i know eval is evil, but i think it's safe here
|
||||
time = eval(time); // jshint ignore:line
|
||||
} catch (e){
|
||||
console.log("problem evaluating Tone.Time: "+oringalTime);
|
||||
time = 0;
|
||||
}
|
||||
} else if (this.isNotation(time)){
|
||||
time = this.notationToSeconds(time);
|
||||
} else if (this.isTransportTime(time)){
|
||||
time = this.transportTimeToSeconds(time);
|
||||
|
@ -898,8 +892,14 @@ function(Tone){
|
|||
}
|
||||
};
|
||||
|
||||
//a single transport object
|
||||
Tone.Transport = new Tone.Transport();
|
||||
Tone._initAudioContext(function(){
|
||||
//replace the previous one if it exists
|
||||
if (Tone.Transport){
|
||||
Tone.Transport.dispose();
|
||||
}
|
||||
//a single transport object
|
||||
Tone.Transport = new Transport();
|
||||
});
|
||||
|
||||
return Tone.Transport;
|
||||
});
|
||||
|
|
Loading…
Reference in a new issue