<commit_before>define(["Tone/core/Tone", "Tone/core/Clock", "Tone/type/Type", "Tone/core/Timeline", 
	"Tone/core/Emitter", "Tone/core/Gain", "Tone/core/IntervalTimeline"], 
function(Tone){

	"use strict";

	/**
	 *  @class  Transport for timing musical events.
	 *          Supports tempo curves and time changes. Unlike browser-based timing (setInterval, requestAnimationFrame)
	 *          Tone.Transport timing events pass in the exact time of the scheduled event
	 *          in the argument of the callback function. Pass that time value to the object
	 *          you're scheduling. <br><br>
	 *          A single transport is created for you when the library is initialized. 
	 *          <br><br>
	 *          The transport emits the events: "start", "stop", "pause", and "loop" which are
	 *          called with the time of that event as the argument. 
	 *
	 *  @extends {Tone.Emitter}
	 *  @singleton
	 *  @example
	 * //repeated event every 8th note
	 * Tone.Transport.scheduleRepeat(function(time){
	 * 	//do something with the time
	 * }, "8n");
	 *  @example
	 * //schedule an event on the 16th measure
	 * Tone.Transport.schedule(function(time){
	 * 	//do something with the time
	 * }, "16:0:0");
	 */
	Tone.Transport = function(){

		Tone.Emitter.call(this);

		///////////////////////////////////////////////////////////////////////
		//	LOOPING
		//////////////////////////////////////////////////////////////////////

		/** 
		 * 	If the transport loops or not.
		 *  @type {boolean}
		 */
		this.loop = false;

		/** 
		 * 	The loop start position in ticks
		 *  @type {Ticks}
		 *  @private
		 */
		this._loopStart = 0;

		/** 
		 * 	The loop end position in ticks
		 *  @type {Ticks}
		 *  @private
		 */
		this._loopEnd = 0;

		///////////////////////////////////////////////////////////////////////
		//	CLOCK/TEMPO
		//////////////////////////////////////////////////////////////////////

		/**
		 *  Pulses per quarter is the number of ticks per quarter note.
		 *  @private
		 *  @type  {Number}
		 */
		this._ppq = TransportConstructor.defaults.PPQ;

		/**
		 *  watches the main oscillator for timing ticks
		 *  initially starts at 120bpm
		 *  @private
		 *  @type {Tone.Clock}
		 */
		this._clock = new Tone.Clock({
			"callback" : this._processTick.bind(this), 
			"frequency" : 0,
		});
		/**
		 *  The Beats Per Minute of the Transport. 
		 *  @type {BPM}
		 *  @signal
		 *  @example
		 * Tone.Transport.bpm.value = 80;
		 * //ramp the bpm to 120 over 10 seconds
		 * Tone.Transport.bpm.rampTo(120, 10);
		 */
		this.bpm = this._clock.frequency;
		this.bpm._toUnits = this._toUnits.bind(this);
		this.bpm._fromUnits = this._fromUnits.bind(this);
		this.bpm.units = Tone.Type.BPM;
		this.bpm.value = TransportConstructor.defaults.bpm;
		this._readOnly("bpm");

		/**
		 *  The time signature, or more accurately the numerator
		 *  of the time signature over a denominator of 4. 
		 *  @type {Number}
		 *  @private
		 */
		this._timeSignature = TransportConstructor.defaults.timeSignature;

		///////////////////////////////////////////////////////////////////////
		//	TIMELINE EVENTS
		//////////////////////////////////////////////////////////////////////

		/**
		 *  All the events in an object to keep track by ID
		 *  @type {Object}
		 *  @private
		 */
		this._scheduledEvents = {};

		/**
		 *  The event ID counter
		 *  @type {Number}
		 *  @private
		 */
		this._eventID = 0;

		/**
		 * 	The scheduled events.
		 *  @type {Tone.Timeline}
		 *  @private
		 */
		this._timeline = new Tone.Timeline();

		/**
		 *  Repeated events
		 *  @type {Array}
		 *  @private
		 */
		this._repeatedEvents = new Tone.IntervalTimeline();

		/**
		 *  Events that occur once
		 *  @type {Array}
		 *  @private
		 */
		this._onceEvents = new Tone.Timeline();

		/** 
		 *  All of the synced Signals
		 *  @private 
		 *  @type {Array}
		 */
		this._syncedSignals = [];

		///////////////////////////////////////////////////////////////////////
		//	SWING
		//////////////////////////////////////////////////////////////////////

		/**
		 *  The subdivision of the swing
		 *  @type  {Ticks}
		 *  @private
		 */
		this._swingTicks = TransportConstructor.defaults.PPQ / 2; //8n

		/**
		 *  The swing amount
		 *  @type {NormalRange}
		 *  @private
		 */
		this._swingAmount = 0;

	};

	Tone.extend(Tone.Transport, Tone.Emitter);

	/**
	 *  the defaults
	 *  @type {Object}
	 *  @const
	 *  @static
	 */
	Tone.Transport.defaults = {
		"bpm" : 120,
		"swing" : 0,
		"swingSubdivision" : "8n",
		"timeSignature" : 4,
		"loopStart" : 0,
		"loopEnd" : "4m",
		"PPQ" : 192
	};

	///////////////////////////////////////////////////////////////////////////////
	//	TICKS
	///////////////////////////////////////////////////////////////////////////////

	/**
	 *  called on every tick
	 *  @param   {number} tickTime clock relative tick time
	 *  @private
	 */
	Tone.Transport.prototype._processTick = function(tickTime){
		var ticks = this._clock.ticks;
		//handle swing
		if (this._swingAmount > 0 && 
			ticks % this._ppq !== 0 && //not on a downbeat
			ticks % (this._swingTicks * 2) !== 0){
			//add some swing
			var progress = (ticks % (this._swingTicks * 2)) / (this._swingTicks * 2);
			var amount = Math.sin((progress) * Math.PI) * this._swingAmount;
			tickTime += Tone.Time(this._swingTicks * 2/3, "i").eval() * amount;
		} 
		//do the loop test
		if (this.loop){
			if (ticks === this._loopEnd){
				this.ticks = this._loopStart;
				ticks = this._loopStart;
				this.trigger("loop", tickTime);
			}
		}
		//process the single occurrence events
		this._onceEvents.forEachBefore(ticks, function(event){
			event.callback(tickTime);
		});
		//and clear the single occurrence timeline
		this._onceEvents.cancelBefore(ticks);
		//fire the next tick events if their time has come
		this._timeline.forEachAtTime(ticks, function(event){
			event.callback(tickTime);
		});
		//process the repeated events
		this._repeatedEvents.forEachOverlap(ticks, function(event){
			if ((ticks - event.time) % event.interval === 0){
				event.callback(tickTime);
			}
		});
	};

	///////////////////////////////////////////////////////////////////////////////
	//	SCHEDULABLE EVENTS
	///////////////////////////////////////////////////////////////////////////////

	/**
	 *  Schedule an event along the timeline.
	 *  @param {Function} callback The callback to be invoked at the time.
	 *  @param {TransportTime}  time The time to invoke the callback at.
	 *  @return {Number} The id of the event which can be used for canceling the event. 
	 *  @example
	 * //trigger the callback when the Transport reaches the desired time
	 * Tone.Transport.schedule(function(time){
	 * 	envelope.triggerAttack(time);
	 * }, "128i");
	 */
	Tone.Transport.prototype.schedule = function(callback, time){
		var event = {
			"time" : this.toTicks(time),
			"callback" : callback
		};
		var id = this._eventID++;
		this._scheduledEvents[id.toString()] = {
			"event" : event,
			"timeline" : this._timeline
		};
		this._timeline.addEvent(event);
		return id;
	};

	/**
	 *  Schedule a repeated event along the timeline. The event will fire
	 *  at the `interval` starting at the `startTime` and for the specified
	 *  `duration`. 
	 *  @param  {Function}  callback   The callback to invoke.
	 *  @param  {Time}    interval   The duration between successive
	 *                               callbacks.
	 *  @param  {TimelinePosition=}    startTime  When along the timeline the events should
	 *                               start being invoked.
	 *  @param {Time} [duration=Infinity] How long the event should repeat. 
	 *  @return  {Number}    The ID of the scheduled event. Use this to cancel
	 *                           the event. 
	 *  @example
	 * //a callback invoked every eighth note after the first measure
	 * Tone.Transport.scheduleRepeat(callback, "8n", "1m");
	 */
	Tone.Transport.prototype.scheduleRepeat = function(callback, interval, startTime, duration){
		if (interval <= 0){
			throw new Error("repeat events must have an interval larger than 0");
		}
		var event = {
			"time" : this.toTicks(startTime),
			"duration" : this.toTicks(this.defaultArg(duration, Infinity)),
			"interval" : this.toTicks(interval),
			"callback" : callback
		};
		var id = this._eventID++;
		this._scheduledEvents[id.toString()] = {
			"event" : event,
			"timeline" : this._repeatedEvents
		};
		this._repeatedEvents.addEvent(event);
		return id;
	};

	/**
	 *  Schedule an event that will be removed after it is invoked. 
	 *  Note that if the given time is less than the current transport time, 
	 *  the event will be invoked immediately. 
	 *  @param {Function} callback The callback to invoke once.
	 *  @param {TransportTime} time The time the callback should be invoked.
	 *  @returns {Number} The ID of the scheduled event. 
	 */
	Tone.Transport.prototype.scheduleOnce = function(callback, time){
		var event = {
			"time" : this.toTicks(time),
			"callback" : callback
		};
		var id = this._eventID++;
		this._scheduledEvents[id.toString()] = {
			"event" : event,
			"timeline" : this._onceEvents
		};
		this._onceEvents.addEvent(event);
		return id;
	};

	/**
	 *  Clear the passed in event id from the timeline
	 *  @param {Number} eventId The id of the event.
	 *  @returns {Tone.Transport} this
	 */
	Tone.Transport.prototype.clear = function(eventId){
		if (this._scheduledEvents.hasOwnProperty(eventId)){
			var item = this._scheduledEvents[eventId.toString()];
			item.timeline.removeEvent(item.event);
			delete this._scheduledEvents[eventId.toString()];
		}
		return this;
	};

	/**
	 *  Remove scheduled events from the timeline after
	 *  the given time. Repeated events will be removed
	 *  if their startTime is after the given time
	 *  @param {TransportTime} [after=0] Clear all events after
	 *                          this time. 
	 *  @returns {Tone.Transport} this
	 */
	Tone.Transport.prototype.cancel = function(after){
		after = this.defaultArg(after, 0);
		after = this.toTicks(after);
		this._timeline.cancel(after);
		this._onceEvents.cancel(after);
		this._repeatedEvents.cancel(after);
		return this;
	};

	///////////////////////////////////////////////////////////////////////////////
	//	START/STOP/PAUSE
	///////////////////////////////////////////////////////////////////////////////

	/**
	 *  Returns the playback state of the source, either "started", "stopped", or "paused"
	 *  @type {Tone.State}
	 *  @readOnly
	 *  @memberOf Tone.Transport#
	 *  @name state
	 */
	Object.defineProperty(Tone.Transport.prototype, "state", {
		get : function(){
			return this._clock.getStateAtTime(this.now());
		}
	});

	/**
	 *  Start the transport and all sources synced to the transport.
	 *  @param  {Time} [time=now] The time when the transport should start.
	 *  @param  {TransportTime=} offset The timeline offset to start the transport.
	 *  @returns {Tone.Transport} this
	 *  @example
	 * //start the transport in one second starting at beginning of the 5th measure. 
	 * Tone.Transport.start("+1", "4:0:0");
	 */
	Tone.Transport.prototype.start = function(time, offset){
		time = this.toSeconds(time);
		if (!this.isUndef(offset)){
			offset = new Tone.Time(offset);
		} else {
			offset = new Tone.Time(this._clock.ticks, "i");
		}
		//start the clock
		this._clock.start(time, offset.toTicks());
		this.trigger("start", time, offset.toSeconds());
		return this;
	};

	/**
	 *  Stop the transport and all sources synced to the transport.
	 *  @param  {Time} [time=now] The time when the transport should stop. 
	 *  @returns {Tone.Transport} this
	 *  @example
	 * Tone.Transport.stop();
	 */
	Tone.Transport.prototype.stop = function(time){
		time = this.toSeconds(time);
		this._clock.stop(time);
		this.trigger("stop", time);
		return this;
	};

	/**
	 *  Pause the transport and all sources synced to the transport.
	 *  @param  {Time} [time=now]
	 *  @returns {Tone.Transport} this
	 */
	Tone.Transport.prototype.pause = function(time){
		time = this.toSeconds(time);
		this._clock.pause(time);
		this.trigger("pause", time);
		return this;
	};

	///////////////////////////////////////////////////////////////////////////////
	//	SETTERS/GETTERS
	///////////////////////////////////////////////////////////////////////////////

	/**
	 *  The time signature as just the numerator over 4. 
	 *  For example 4/4 would be just 4 and 6/8 would be 3.
	 *  @memberOf Tone.Transport#
	 *  @type {Number|Array}
	 *  @name timeSignature
	 *  @example
	 * //common time
	 * Tone.Transport.timeSignature = 4;
	 * // 7/8
	 * Tone.Transport.timeSignature = [7, 8];
	 * //this will be reduced to a single number
	 * Tone.Transport.timeSignature; //returns 3.5
	 */
	Object.defineProperty(Tone.Transport.prototype, "timeSignature", {
		get : function(){
			return this._timeSignature;
		},
		set : function(timeSig){
			if (this.isArray(timeSig)){
				timeSig = (timeSig[0] / timeSig[1]) * 4;
			}
			this._timeSignature = timeSig;
		}
	});


	/**
	 * When the Tone.Transport.loop = true, this is the starting position of the loop.
	 * @memberOf Tone.Transport#
	 * @type {TransportTime}
	 * @name loopStart
	 */
	Object.defineProperty(Tone.Transport.prototype, "loopStart", {
		get : function(){
			return Tone.TransportTime(this._loopStart, "i").toSeconds();
		},
		set : function(startPosition){
			this._loopStart = this.toTicks(startPosition);
		}
	});

	/**
	 * When the Tone.Transport.loop = true, this is the ending position of the loop.
	 * @memberOf Tone.Transport#
	 * @type {TransportTime}
	 * @name loopEnd
	 */
	Object.defineProperty(Tone.Transport.prototype, "loopEnd", {
		get : function(){
			return Tone.TransportTime(this._loopEnd, "i").toSeconds();
		},
		set : function(endPosition){
			this._loopEnd = this.toTicks(endPosition);
		}
	});

	/**
	 *  Set the loop start and stop at the same time. 
	 *  @param {TransportTime} startPosition 
	 *  @param {TransportTime} endPosition   
	 *  @returns {Tone.Transport} this
	 *  @example
	 * //loop over the first measure
	 * Tone.Transport.setLoopPoints(0, "1m");
	 * Tone.Transport.loop = true;
	 */
	Tone.Transport.prototype.setLoopPoints = function(startPosition, endPosition){
		this.loopStart = startPosition;
		this.loopEnd = endPosition;
		return this;
	};

	/**
	 *  The swing value. Between 0-1 where 1 equal to 
	 *  the note + half the subdivision.
	 *  @memberOf Tone.Transport#
	 *  @type {NormalRange}
	 *  @name swing
	 */
	Object.defineProperty(Tone.Transport.prototype, "swing", {
		get : function(){
			return this._swingAmount;
		},
		set : function(amount){
			//scale the values to a normal range
			this._swingAmount = amount;
		}
	});

	/**
	 *  Set the subdivision which the swing will be applied to. 
	 *  The default values is a 16th note. Value must be less 
	 *  than a quarter note.
	 *  
	 *  @memberOf Tone.Transport#
	 *  @type {Time}
	 *  @name swingSubdivision
	 */
	Object.defineProperty(Tone.Transport.prototype, "swingSubdivision", {
		get : function(){
			return Tone.Time(this._swingTicks, "i").toNotation();
		},
		set : function(subdivision){
			this._swingTicks = this.toTicks(subdivision);
		}
	});

	/**
	 *  The Transport's position in Bars:Beats:Sixteenths.
	 *  Setting the value will jump to that position right away. 
	 *  @memberOf Tone.Transport#
	 *  @type {TransportTime}
	 *  @name position
	 */
	Object.defineProperty(Tone.Transport.prototype, "position", {
		get : function(){
			var quarters = this.ticks / this._ppq;
			var measures = Math.floor(quarters / this._timeSignature);
			var sixteenths = ((quarters % 1) * 4);
			//if the sixteenths aren't a whole number, fix their length
			if (sixteenths % 1 > 0){
				sixteenths = sixteenths.toFixed(3);	
			}
			quarters = Math.floor(quarters) % this._timeSignature;
			var progress = [measures, quarters, sixteenths];
			return progress.join(":");
		},
		set : function(progress){
			var ticks = this.toTicks(progress);
			this.ticks = ticks;
		}
	});

	/**
	 *  The Transport's loop position as a normalized value. Always
	 *  returns 0 if the transport if loop is not true. 
	 *  @memberOf Tone.Transport#<commit_msg>simplifying `position` code to use TransportTime<commit_after>define(["Tone/core/Tone", "Tone/core/Clock", "Tone/type/Type", "Tone/core/Timeline", 
	"Tone/core/Emitter", "Tone/core/Gain", "Tone/core/IntervalTimeline"], 
function(Tone){

	"use strict";

	/**
	 *  @class  Transport for timing musical events.
	 *          Supports tempo curves and time changes. Unlike browser-based timing (setInterval, requestAnimationFrame)
	 *          Tone.Transport timing events pass in the exact time of the scheduled event
	 *          in the argument of the callback function. Pass that time value to the object
	 *          you're scheduling. <br><br>
	 *          A single transport is created for you when the library is initialized. 
	 *          <br><br>
	 *          The transport emits the events: "start", "stop", "pause", and "loop" which are
	 *          called with the time of that event as the argument. 
	 *
	 *  @extends {Tone.Emitter}
	 *  @singleton
	 *  @example
	 * //repeated event every 8th note
	 * Tone.Transport.scheduleRepeat(function(time){
	 * 	//do something with the time
	 * }, "8n");
	 *  @example
	 * //schedule an event on the 16th measure
	 * Tone.Transport.schedule(function(time){
	 * 	//do something with the time
	 * }, "16:0:0");
	 */
	Tone.Transport = function(){

		Tone.Emitter.call(this);

		///////////////////////////////////////////////////////////////////////
		//	LOOPING
		//////////////////////////////////////////////////////////////////////

		/** 
		 * 	If the transport loops or not.
		 *  @type {boolean}
		 */
		this.loop = false;

		/** 
		 * 	The loop start position in ticks
		 *  @type {Ticks}
		 *  @private
		 */
		this._loopStart = 0;

		/** 
		 * 	The loop end position in ticks
		 *  @type {Ticks}
		 *  @private
		 */
		this._loopEnd = 0;

		///////////////////////////////////////////////////////////////////////
		//	CLOCK/TEMPO
		//////////////////////////////////////////////////////////////////////

		/**
		 *  Pulses per quarter is the number of ticks per quarter note.
		 *  @private
		 *  @type  {Number}
		 */
		this._ppq = TransportConstructor.defaults.PPQ;

		/**
		 *  watches the main oscillator for timing ticks
		 *  initially starts at 120bpm
		 *  @private
		 *  @type {Tone.Clock}
		 */
		this._clock = new Tone.Clock({
			"callback" : this._processTick.bind(this), 
			"frequency" : 0,
		});
		/**
		 *  The Beats Per Minute of the Transport. 
		 *  @type {BPM}
		 *  @signal
		 *  @example
		 * Tone.Transport.bpm.value = 80;
		 * //ramp the bpm to 120 over 10 seconds
		 * Tone.Transport.bpm.rampTo(120, 10);
		 */
		this.bpm = this._clock.frequency;
		this.bpm._toUnits = this._toUnits.bind(this);
		this.bpm._fromUnits = this._fromUnits.bind(this);
		this.bpm.units = Tone.Type.BPM;
		this.bpm.value = TransportConstructor.defaults.bpm;
		this._readOnly("bpm");

		/**
		 *  The time signature, or more accurately the numerator
		 *  of the time signature over a denominator of 4. 
		 *  @type {Number}
		 *  @private
		 */
		this._timeSignature = TransportConstructor.defaults.timeSignature;

		///////////////////////////////////////////////////////////////////////
		//	TIMELINE EVENTS
		//////////////////////////////////////////////////////////////////////

		/**
		 *  All the events in an object to keep track by ID
		 *  @type {Object}
		 *  @private
		 */
		this._scheduledEvents = {};

		/**
		 *  The event ID counter
		 *  @type {Number}
		 *  @private
		 */
		this._eventID = 0;

		/**
		 * 	The scheduled events.
		 *  @type {Tone.Timeline}
		 *  @private
		 */
		this._timeline = new Tone.Timeline();

		/**
		 *  Repeated events
		 *  @type {Array}
		 *  @private
		 */
		this._repeatedEvents = new Tone.IntervalTimeline();

		/**
		 *  Events that occur once
		 *  @type {Array}
		 *  @private
		 */
		this._onceEvents = new Tone.Timeline();

		/** 
		 *  All of the synced Signals
		 *  @private 
		 *  @type {Array}
		 */
		this._syncedSignals = [];

		///////////////////////////////////////////////////////////////////////
		//	SWING
		//////////////////////////////////////////////////////////////////////

		/**
		 *  The subdivision of the swing
		 *  @type  {Ticks}
		 *  @private
		 */
		this._swingTicks = TransportConstructor.defaults.PPQ / 2; //8n

		/**
		 *  The swing amount
		 *  @type {NormalRange}
		 *  @private
		 */
		this._swingAmount = 0;

	};

	Tone.extend(Tone.Transport, Tone.Emitter);

	/**
	 *  the defaults
	 *  @type {Object}
	 *  @const
	 *  @static
	 */
	Tone.Transport.defaults = {
		"bpm" : 120,
		"swing" : 0,
		"swingSubdivision" : "8n",
		"timeSignature" : 4,
		"loopStart" : 0,
		"loopEnd" : "4m",
		"PPQ" : 192
	};

	///////////////////////////////////////////////////////////////////////////////
	//	TICKS
	///////////////////////////////////////////////////////////////////////////////

	/**
	 *  called on every tick
	 *  @param   {number} tickTime clock relative tick time
	 *  @private
	 */
	Tone.Transport.prototype._processTick = function(tickTime){
		var ticks = this._clock.ticks;
		//handle swing
		if (this._swingAmount > 0 && 
			ticks % this._ppq !== 0 && //not on a downbeat
			ticks % (this._swingTicks * 2) !== 0){
			//add some swing
			var progress = (ticks % (this._swingTicks * 2)) / (this._swingTicks * 2);
			var amount = Math.sin((progress) * Math.PI) * this._swingAmount;
			tickTime += Tone.Time(this._swingTicks * 2/3, "i").eval() * amount;
		} 
		//do the loop test
		if (this.loop){
			if (ticks === this._loopEnd){
				this.ticks = this._loopStart;
				ticks = this._loopStart;
				this.trigger("loop", tickTime);
			}
		}
		//process the single occurrence events
		this._onceEvents.forEachBefore(ticks, function(event){
			event.callback(tickTime);
		});
		//and clear the single occurrence timeline
		this._onceEvents.cancelBefore(ticks);
		//fire the next tick events if their time has come
		this._timeline.forEachAtTime(ticks, function(event){
			event.callback(tickTime);
		});
		//process the repeated events
		this._repeatedEvents.forEachOverlap(ticks, function(event){
			if ((ticks - event.time) % event.interval === 0){
				event.callback(tickTime);
			}
		});
	};

	///////////////////////////////////////////////////////////////////////////////
	//	SCHEDULABLE EVENTS
	///////////////////////////////////////////////////////////////////////////////

	/**
	 *  Schedule an event along the timeline.
	 *  @param {Function} callback The callback to be invoked at the time.
	 *  @param {TransportTime}  time The time to invoke the callback at.
	 *  @return {Number} The id of the event which can be used for canceling the event. 
	 *  @example
	 * //trigger the callback when the Transport reaches the desired time
	 * Tone.Transport.schedule(function(time){
	 * 	envelope.triggerAttack(time);
	 * }, "128i");
	 */
	Tone.Transport.prototype.schedule = function(callback, time){
		var event = {
			"time" : this.toTicks(time),
			"callback" : callback
		};
		var id = this._eventID++;
		this._scheduledEvents[id.toString()] = {
			"event" : event,
			"timeline" : this._timeline
		};
		this._timeline.addEvent(event);
		return id;
	};

	/**
	 *  Schedule a repeated event along the timeline. The event will fire
	 *  at the `interval` starting at the `startTime` and for the specified
	 *  `duration`. 
	 *  @param  {Function}  callback   The callback to invoke.
	 *  @param  {Time}    interval   The duration between successive
	 *                               callbacks.
	 *  @param  {TimelinePosition=}    startTime  When along the timeline the events should
	 *                               start being invoked.
	 *  @param {Time} [duration=Infinity] How long the event should repeat. 
	 *  @return  {Number}    The ID of the scheduled event. Use this to cancel
	 *                           the event. 
	 *  @example
	 * //a callback invoked every eighth note after the first measure
	 * Tone.Transport.scheduleRepeat(callback, "8n", "1m");
	 */
	Tone.Transport.prototype.scheduleRepeat = function(callback, interval, startTime, duration){
		if (interval <= 0){
			throw new Error("repeat events must have an interval larger than 0");
		}
		var event = {
			"time" : this.toTicks(startTime),
			"duration" : this.toTicks(this.defaultArg(duration, Infinity)),
			"interval" : this.toTicks(interval),
			"callback" : callback
		};
		var id = this._eventID++;
		this._scheduledEvents[id.toString()] = {
			"event" : event,
			"timeline" : this._repeatedEvents
		};
		this._repeatedEvents.addEvent(event);
		return id;
	};

	/**
	 *  Schedule an event that will be removed after it is invoked. 
	 *  Note that if the given time is less than the current transport time, 
	 *  the event will be invoked immediately. 
	 *  @param {Function} callback The callback to invoke once.
	 *  @param {TransportTime} time The time the callback should be invoked.
	 *  @returns {Number} The ID of the scheduled event. 
	 */
	Tone.Transport.prototype.scheduleOnce = function(callback, time){
		var event = {
			"time" : this.toTicks(time),
			"callback" : callback
		};
		var id = this._eventID++;
		this._scheduledEvents[id.toString()] = {
			"event" : event,
			"timeline" : this._onceEvents
		};
		this._onceEvents.addEvent(event);
		return id;
	};

	/**
	 *  Clear the passed in event id from the timeline
	 *  @param {Number} eventId The id of the event.
	 *  @returns {Tone.Transport} this
	 */
	Tone.Transport.prototype.clear = function(eventId){
		if (this._scheduledEvents.hasOwnProperty(eventId)){
			var item = this._scheduledEvents[eventId.toString()];
			item.timeline.removeEvent(item.event);
			delete this._scheduledEvents[eventId.toString()];
		}
		return this;
	};

	/**
	 *  Remove scheduled events from the timeline after
	 *  the given time. Repeated events will be removed
	 *  if their startTime is after the given time
	 *  @param {TransportTime} [after=0] Clear all events after
	 *                          this time. 
	 *  @returns {Tone.Transport} this
	 */
	Tone.Transport.prototype.cancel = function(after){
		after = this.defaultArg(after, 0);
		after = this.toTicks(after);
		this._timeline.cancel(after);
		this._onceEvents.cancel(after);
		this._repeatedEvents.cancel(after);
		return this;
	};

	///////////////////////////////////////////////////////////////////////////////
	//	START/STOP/PAUSE
	///////////////////////////////////////////////////////////////////////////////

	/**
	 *  Returns the playback state of the source, either "started", "stopped", or "paused"
	 *  @type {Tone.State}
	 *  @readOnly
	 *  @memberOf Tone.Transport#
	 *  @name state
	 */
	Object.defineProperty(Tone.Transport.prototype, "state", {
		get : function(){
			return this._clock.getStateAtTime(this.now());
		}
	});

	/**
	 *  Start the transport and all sources synced to the transport.
	 *  @param  {Time} [time=now] The time when the transport should start.
	 *  @param  {TransportTime=} offset The timeline offset to start the transport.
	 *  @returns {Tone.Transport} this
	 *  @example
	 * //start the transport in one second starting at beginning of the 5th measure. 
	 * Tone.Transport.start("+1", "4:0:0");
	 */
	Tone.Transport.prototype.start = function(time, offset){
		time = this.toSeconds(time);
		if (!this.isUndef(offset)){
			offset = new Tone.Time(offset);
		} else {
			offset = new Tone.Time(this._clock.ticks, "i");
		}
		//start the clock
		this._clock.start(time, offset.toTicks());
		this.trigger("start", time, offset.toSeconds());
		return this;
	};

	/**
	 *  Stop the transport and all sources synced to the transport.
	 *  @param  {Time} [time=now] The time when the transport should stop. 
	 *  @returns {Tone.Transport} this
	 *  @example
	 * Tone.Transport.stop();
	 */
	Tone.Transport.prototype.stop = function(time){
		time = this.toSeconds(time);
		this._clock.stop(time);
		this.trigger("stop", time);
		return this;
	};

	/**
	 *  Pause the transport and all sources synced to the transport.
	 *  @param  {Time} [time=now]
	 *  @returns {Tone.Transport} this
	 */
	Tone.Transport.prototype.pause = function(time){
		time = this.toSeconds(time);
		this._clock.pause(time);
		this.trigger("pause", time);
		return this;
	};

	///////////////////////////////////////////////////////////////////////////////
	//	SETTERS/GETTERS
	///////////////////////////////////////////////////////////////////////////////

	/**
	 *  The time signature as just the numerator over 4. 
	 *  For example 4/4 would be just 4 and 6/8 would be 3.
	 *  @memberOf Tone.Transport#
	 *  @type {Number|Array}
	 *  @name timeSignature
	 *  @example
	 * //common time
	 * Tone.Transport.timeSignature = 4;
	 * // 7/8
	 * Tone.Transport.timeSignature = [7, 8];
	 * //this will be reduced to a single number
	 * Tone.Transport.timeSignature; //returns 3.5
	 */
	Object.defineProperty(Tone.Transport.prototype, "timeSignature", {
		get : function(){
			return this._timeSignature;
		},
		set : function(timeSig){
			if (this.isArray(timeSig)){
				timeSig = (timeSig[0] / timeSig[1]) * 4;
			}
			this._timeSignature = timeSig;
		}
	});


	/**
	 * When the Tone.Transport.loop = true, this is the starting position of the loop.
	 * @memberOf Tone.Transport#
	 * @type {TransportTime}
	 * @name loopStart
	 */
	Object.defineProperty(Tone.Transport.prototype, "loopStart", {
		get : function(){
			return Tone.TransportTime(this._loopStart, "i").toSeconds();
		},
		set : function(startPosition){
			this._loopStart = this.toTicks(startPosition);
		}
	});

	/**
	 * When the Tone.Transport.loop = true, this is the ending position of the loop.
	 * @memberOf Tone.Transport#
	 * @type {TransportTime}
	 * @name loopEnd
	 */
	Object.defineProperty(Tone.Transport.prototype, "loopEnd", {
		get : function(){
			return Tone.TransportTime(this._loopEnd, "i").toSeconds();
		},
		set : function(endPosition){
			this._loopEnd = this.toTicks(endPosition);
		}
	});

	/**
	 *  Set the loop start and stop at the same time. 
	 *  @param {TransportTime} startPosition 
	 *  @param {TransportTime} endPosition   
	 *  @returns {Tone.Transport} this
	 *  @example
	 * //loop over the first measure
	 * Tone.Transport.setLoopPoints(0, "1m");
	 * Tone.Transport.loop = true;
	 */
	Tone.Transport.prototype.setLoopPoints = function(startPosition, endPosition){
		this.loopStart = startPosition;
		this.loopEnd = endPosition;
		return this;
	};

	/**
	 *  The swing value. Between 0-1 where 1 equal to 
	 *  the note + half the subdivision.
	 *  @memberOf Tone.Transport#
	 *  @type {NormalRange}
	 *  @name swing
	 */
	Object.defineProperty(Tone.Transport.prototype, "swing", {
		get : function(){
			return this._swingAmount;
		},
		set : function(amount){
			//scale the values to a normal range
			this._swingAmount = amount;
		}
	});

	/**
	 *  Set the subdivision which the swing will be applied to. 
	 *  The default values is a 16th note. Value must be less 
	 *  than a quarter note.
	 *  
	 *  @memberOf Tone.Transport#
	 *  @type {Time}
	 *  @name swingSubdivision
	 */
	Object.defineProperty(Tone.Transport.prototype, "swingSubdivision", {
		get : function(){
			return Tone.Time(this._swingTicks, "i").toNotation();
		},
		set : function(subdivision){
			this._swingTicks = this.toTicks(subdivision);
		}
	});

	/**
	 *  The Transport's position in Bars:Beats:Sixteenths.
	 *  Setting the value will jump to that position right away. 
	 *  @memberOf Tone.Transport#
	 *  @type {BarsBeatsSixteenths}
	 *  @name position
	 */
	Object.defineProperty(Tone.Transport.prototype, "position", {
		get : function(){
			return Tone.TransportTime(this.ticks, "i").toBarsBeatsSixteenths();
		},
		set : function(progress){
			var ticks = this.toTicks(progress);
			this.ticks = ticks;
		}
	});

	/**
	 *  The Transport's loop position as a normalized value. Always
	 *  returns 0 if the transport if loop is not true. 
	 *  @memberOf Tone.Transport#
{'fraction_non_alphanumeric': 0.1969891396200432, 'fraction_numerical': 0.005790116115301555, 'mean_word_length': 2.20545746388443, 'pattern_counts': {'":': 1, '<': 13, '<?xml version=': 0, '>': 14, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 6, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4973284', 'n_tokens_mistral': 10924, 'n_tokens_neox': 9465, 'n_words': 2606}