<commit_before>define(["Tone/core/Tone", "Tone/core/Buffer", "Tone/source/Source"], function(Tone){

	"use strict";

	/**
	 *  @class  Tone.Player is an audio file player with start, loop, and stop functions.
	 *
	 *  @constructor
	 *  @extends {Tone.Source}
	 *  @param {string|AudioBuffer} url Either the AudioBuffer or the url from
	 *                                  which to load the AudioBuffer
	 *  @param {function=} onload The function to invoke when the buffer is loaded. 
	 *                            Recommended to use Tone.Buffer.onload instead.
	 *  @example
	 * var player = new Tone.Player("./path/to/sample.mp3").toMaster();
	 * Tone.Buffer.onload = function(){
	 * 	player.start();
	 * }
	 */
	Tone.Player = function(){

		var options = this.optionsObject(arguments, ["url", "onload"], Tone.Player.defaults);
		Tone.Source.call(this, options);

		/**
		 *  @private
		 *  @type {AudioBufferSourceNode}
		 */
		this._source = null;

		/**
		 *  If the file should play as soon
		 *  as the buffer is loaded. 
		 *  @type {boolean}
		 *  @example
		 * //will play as soon as it's loaded
		 * var player = new Tone.Player({
		 * 	"url" : "./path/to/sample.mp3",
		 * 	"autostart" : true,
		 * }).toMaster();
		 */
		this.autostart = options.autostart;

		/**
		 *  the buffer
		 *  @private
		 *  @type {Tone.Buffer}
		 */
		this._buffer = new Tone.Buffer({
			"url" : options.url, 
			"onload" : this._onload.bind(this, options.onload),
			"reverse" : options.reverse
		});

		/**
		 *  The position the sample will start playback from
		 *  @type {Tone.Time}
		 *  @private
		 */
		this._startPosition = options.startPosition;

		/**
		 *  if the buffer should loop once it's over
		 *  @type {boolean}
		 *  @private
		 */
		this._loop = options.loop;

		/**
		 *  if 'loop' is true, the loop will start at this position
		 *  @type {Time}
		 *  @private
		 */
		this._loopStart = options.loopStart;

		/**
		 *  if 'loop' is true, the loop will end at this position
		 *  @type {Time}
		 *  @private
		 */
		this._loopEnd = options.loopEnd;

		/**
		 *  the playback rate
		 *  @private
		 *  @type {number}
		 */
		this._playbackRate = options.playbackRate;

		/**
		 *  Enabling retrigger will allow a player to be restarted
		 *  before the the previous 'start' is done playing. Otherwise, 
		 *  successive calls to Tone.Player.start will only start
		 *  the sample if it had played all the way through. 
		 *  @type {boolean}
		 */
		this.retrigger = options.retrigger;
	};

	Tone.extend(Tone.Player, Tone.Source);

	/**
	 *  the default parameters
	 *  @static
	 *  @const
	 *  @type {Object}
	 */
	Tone.Player.defaults = {
		"onload" : Tone.noOp,
		"playbackRate" : 1,
		"loop" : false,
		"autostart" : false,
		"loopStart" : 0,
		"loopEnd" : 0,
		"retrigger" : false,
		"reverse" : false,
	};

	/**
	 *  Load the audio file as an audio buffer.
	 *  Decodes the audio asynchronously and invokes
	 *  the callback once the audio buffer loads.
	 *  Note: this does not need to be called, if a url
	 *  was passed in to the constructor. Only use this
	 *  if you want to manually load a new url.
	 * @param {string} url The url of the buffer to load.
	 *                     Filetype support depends on the
	 *                     browser.
	 *  @param  {function=} callback The function to invoke once
	 *                               the sample is loaded.
	 *  @returns {Tone.Player} this
	 */
	Tone.Player.prototype.load = function(url, callback){
		this._buffer.load(url, this._onload.bind(this, callback));
		return this;
	};

	/**
	 * Internal callback when the buffer is loaded.
	 * @private
	 */
	Tone.Player.prototype._onload = function(callback){
		callback(this);
		if (this.autostart){
			this.start();
		}
	};

	/**
	 *  play the buffer between the desired positions
	 *
	 *  @private
	 *  @param  {Time} [startTime=now] when the player should start.
	 *  @param  {Time} [offset=0] the offset from the beginning of the sample
	 *                                 to start at. 
	 *  @param  {Time=} duration how long the sample should play. If no duration
	 *                                is given, it will default to the full length
	 *                                of the sample (minus any offset)
	 *  @returns {Tone.Player} this
	 */
	Tone.Player.prototype._start = function(startTime, offset, duration){
		if (this._buffer.loaded){
			//if it's a loop the default offset is the loopstart point
			if (this._loop){
				offset = this.defaultArg(offset, this._loopStart);
			} else {
				//otherwise the default offset is 0
				offset = this.defaultArg(this._startPosition, 0);
			}
			offset = this.toSeconds(offset);
			duration = this.defaultArg(duration, this._buffer.duration - offset);
			//the values in seconds
			startTime = this.toSeconds(startTime);
			duration = this.toSeconds(duration);
			//make the source
			this._source = this.context.createBufferSource();
			this._source.buffer = this._buffer.get();
			//set the looping properties
			if (this._loop){
				this._source.loop = this._loop;
				this._source.loopStart = this.toSeconds(this._loopStart);
				this._source.loopEnd = this.toSeconds(this._loopEnd);
				// this fixes a bug in chrome 42 that breaks looping
				// https://code.google.com/p/chromium/issues/detail?id=457099
				duration = 65536;
			} else {
				this._nextStop = startTime + duration;
			}
			//and other properties
			this._source.playbackRate.value = this._playbackRate;
			this._source.onended = this.onended;
			this._source.connect(this.output);
			//start it
			this._source.start(startTime, offset, duration);
		} else {
			throw Error("tried to start Player before the buffer was loaded");
		}
		return this;
	};

	/**
	 *  Stop playback.
	 *  @private
	 *  @param  {Time} [time=now]
	 *  @returns {Tone.Player} this
	 */
	Tone.Player.prototype._stop = function(time){
		if (this._source){
			this._source.stop(this.toSeconds(time));
			this._source = null;
		}
		return this;
	};

	/**
	 *  Set the loop start and end. Will only loop if loop is 
	 *  set to true. 
	 *  @param {Time} loopStart The loop end time
	 *  @param {Time} loopEnd The loop end time
	 *  @returns {Tone.Player} this
	 *  @example
	 * //loop 0.1 seconds of the file. 
	 * player.setLoopPoints(0.2, 0.3);
	 * player.loop = true;<commit_msg>Console log this buffer error instead of halting the function<commit_after>define(["Tone/core/Tone", "Tone/core/Buffer", "Tone/source/Source"], function(Tone){

	"use strict";

	/**
	 *  @class  Tone.Player is an audio file player with start, loop, and stop functions.
	 *
	 *  @constructor
	 *  @extends {Tone.Source}
	 *  @param {string|AudioBuffer} url Either the AudioBuffer or the url from
	 *                                  which to load the AudioBuffer
	 *  @param {function=} onload The function to invoke when the buffer is loaded. 
	 *                            Recommended to use Tone.Buffer.onload instead.
	 *  @example
	 * var player = new Tone.Player("./path/to/sample.mp3").toMaster();
	 * Tone.Buffer.onload = function(){
	 * 	player.start();
	 * }
	 */
	Tone.Player = function(){

		var options = this.optionsObject(arguments, ["url", "onload"], Tone.Player.defaults);
		Tone.Source.call(this, options);

		/**
		 *  @private
		 *  @type {AudioBufferSourceNode}
		 */
		this._source = null;

		/**
		 *  If the file should play as soon
		 *  as the buffer is loaded. 
		 *  @type {boolean}
		 *  @example
		 * //will play as soon as it's loaded
		 * var player = new Tone.Player({
		 * 	"url" : "./path/to/sample.mp3",
		 * 	"autostart" : true,
		 * }).toMaster();
		 */
		this.autostart = options.autostart;

		/**
		 *  the buffer
		 *  @private
		 *  @type {Tone.Buffer}
		 */
		this._buffer = new Tone.Buffer({
			"url" : options.url, 
			"onload" : this._onload.bind(this, options.onload),
			"reverse" : options.reverse
		});

		/**
		 *  The position the sample will start playback from
		 *  @type {Tone.Time}
		 *  @private
		 */
		this._startPosition = options.startPosition;

		/**
		 *  if the buffer should loop once it's over
		 *  @type {boolean}
		 *  @private
		 */
		this._loop = options.loop;

		/**
		 *  if 'loop' is true, the loop will start at this position
		 *  @type {Time}
		 *  @private
		 */
		this._loopStart = options.loopStart;

		/**
		 *  if 'loop' is true, the loop will end at this position
		 *  @type {Time}
		 *  @private
		 */
		this._loopEnd = options.loopEnd;

		/**
		 *  the playback rate
		 *  @private
		 *  @type {number}
		 */
		this._playbackRate = options.playbackRate;

		/**
		 *  Enabling retrigger will allow a player to be restarted
		 *  before the the previous 'start' is done playing. Otherwise, 
		 *  successive calls to Tone.Player.start will only start
		 *  the sample if it had played all the way through. 
		 *  @type {boolean}
		 */
		this.retrigger = options.retrigger;
	};

	Tone.extend(Tone.Player, Tone.Source);

	/**
	 *  the default parameters
	 *  @static
	 *  @const
	 *  @type {Object}
	 */
	Tone.Player.defaults = {
		"onload" : Tone.noOp,
		"playbackRate" : 1,
		"loop" : false,
		"autostart" : false,
		"loopStart" : 0,
		"loopEnd" : 0,
		"retrigger" : false,
		"reverse" : false,
	};

	/**
	 *  Load the audio file as an audio buffer.
	 *  Decodes the audio asynchronously and invokes
	 *  the callback once the audio buffer loads.
	 *  Note: this does not need to be called, if a url
	 *  was passed in to the constructor. Only use this
	 *  if you want to manually load a new url.
	 * @param {string} url The url of the buffer to load.
	 *                     Filetype support depends on the
	 *                     browser.
	 *  @param  {function=} callback The function to invoke once
	 *                               the sample is loaded.
	 *  @returns {Tone.Player} this
	 */
	Tone.Player.prototype.load = function(url, callback){
		this._buffer.load(url, this._onload.bind(this, callback));
		return this;
	};

	/**
	 * Internal callback when the buffer is loaded.
	 * @private
	 */
	Tone.Player.prototype._onload = function(callback){
		callback(this);
		if (this.autostart){
			this.start();
		}
	};

	/**
	 *  play the buffer between the desired positions
	 *
	 *  @private
	 *  @param  {Time} [startTime=now] when the player should start.
	 *  @param  {Time} [offset=0] the offset from the beginning of the sample
	 *                                 to start at. 
	 *  @param  {Time=} duration how long the sample should play. If no duration
	 *                                is given, it will default to the full length
	 *                                of the sample (minus any offset)
	 *  @returns {Tone.Player} this
	 */
	Tone.Player.prototype._start = function(startTime, offset, duration){
		if (this._buffer.loaded){
			//if it's a loop the default offset is the loopstart point
			if (this._loop){
				offset = this.defaultArg(offset, this._loopStart);
			} else {
				//otherwise the default offset is 0
				offset = this.defaultArg(this._startPosition, 0);
			}
			offset = this.toSeconds(offset);
			duration = this.defaultArg(duration, this._buffer.duration - offset);
			//the values in seconds
			startTime = this.toSeconds(startTime);
			duration = this.toSeconds(duration);
			//make the source
			this._source = this.context.createBufferSource();
			this._source.buffer = this._buffer.get();
			//set the looping properties
			if (this._loop){
				this._source.loop = this._loop;
				this._source.loopStart = this.toSeconds(this._loopStart);
				this._source.loopEnd = this.toSeconds(this._loopEnd);
				// this fixes a bug in chrome 42 that breaks looping
				// https://code.google.com/p/chromium/issues/detail?id=457099
				duration = 65536;
			} else {
				this._nextStop = startTime + duration;
			}
			//and other properties
			this._source.playbackRate.value = this._playbackRate;
			this._source.onended = this.onended;
			this._source.connect(this.output);
			//start it
			this._source.start(startTime, offset, duration);
		} else {
			console.log("tried to start Player before the buffer was loaded");
		}
		return this;
	};

	/**
	 *  Stop playback.
	 *  @private
	 *  @param  {Time} [time=now]
	 *  @returns {Tone.Player} this
	 */
	Tone.Player.prototype._stop = function(time){
		if (this._source){
			this._source.stop(this.toSeconds(time));
			this._source = null;
		}
		return this;
	};

	/**
	 *  Set the loop start and end. Will only loop if loop is 
	 *  set to true. 
	 *  @param {Time} loopStart The loop end time
	 *  @param {Time} loopEnd The loop end time
	 *  @returns {Tone.Player} this
	 *  @example
	 * //loop 0.1 seconds of the file. 
	 * player.setLoopPoints(0.2, 0.3);
	 * player.loop = true;
{'fraction_non_alphanumeric': 0.12484207201516109, 'fraction_numerical': 0.004264055590650663, 'mean_word_length': 2.494757174392936, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 14, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5591201', 'n_tokens_mistral': 4582, 'n_tokens_neox': 3918, 'n_words': 1183}